Rex W. Douglass
Data Availability and Interpolation over Time
#test <- lhs_long %>% group_by(dataset, gid, geonameid, wikidata_id, date_asdate) %>% summarize(n=n())
all_na <- function(x) any(!is.na(x)) #https://intellipaat.com/community/12999/remove-columns-from-dataframe-where-all-values-are-na
#bing looks off by a day from the other ones
lhs_wide_qcode <- lhs_long %>%
filter(!is.na(wikidata_id) & !is.na(date_asdate)) %>%
group_by(gid, geonameid, wikidata_id, date_asdate) %>% mutate(confirmed_var=var(confirmed, na.rm=T), deaths_var=var(deaths, na.rm=T)) %>% ungroup() %>%
dplyr::select(dataset, gid, geonameid, wikidata_id, date_asdate,confirmed, deaths, tested_samples, tested_people) %>%
group_by(dataset, gid, geonameid, wikidata_id, date_asdate) %>% summarise_if(is.numeric,max,na.rm=T) %>% ungroup() %>% #this is a hack, we should have dupes within datasets
pivot_wider(names_from = dataset, values_from = c(confirmed, deaths, tested_samples, tested_people) ) %>%
mutate_if(is.numeric, list(~na_if(abs(.), Inf))) %>% #https://stackoverflow.com/questions/12188509/cleaning-inf-values-from-an-r-dataframe
select_if(all_na)
Here we do the actual interpolation. For each individual location-dataset, we fit a piecewise linear model over time, and then use that to average over day to day noise and interpolate between observations. Because this is in log space, the slope of that line is the day on day percent increase in the count. We finish by fitting a piecewise intercept model to those slopes to get a single daily estimate of how much the count is increasing. Datasets are able to disagree in lots of different ways and we still recover a correct rate of change.
Interpolation of Counts
To each individual dataset-location series, we fit a piecewise linear trend. Each segment is required to have at least 3 observations, but otherwise we make no other constraints. This allows us to flexibly fit linear segments as well as tight curves. We also allow for structural breaks where the series stops, has a structural shift up or down because say a change in reporting rules, but other then otherwise continues as normal. We take the linear trend fit as our best estimate at each point. This averages over day to day noise, e.g. under reporting on the weekend. It also allows us to interpolate between observations where there is missingness in the series but we have reasonable beliefs the true measure continued linearly between the observed points.
dataset_places <- lhs_long_clean %>% dplyr::select(dataset_gid_geonameid_wikidata_id) %>% distinct() %>% pull(dataset_gid_geonameid_wikidata_id)
library(party)
temp_list1 <- list()
for(q in dataset_places ){
try({
temp <- NULL
temp <- lhs_long_clean %>%
filter(dataset_gid_geonameid_wikidata_id %in% q) %>%
arrange(date_asdate) %>%
mutate(confirmed_log=log(confirmed)) %>%
mutate(deaths_log=log(deaths)) %>%
mutate(tested_people_log=log(tested_people)) %>%
mutate(tested_samples_log=log(tested_samples))
if(nrow(temp)==0){next()}
temp <- temp %>% expand(dataset, gid_geonameid_wikidata_id, gid, geonameid,wikidata_id, date_asdate=min(date_asdate):max(date_asdate) %>% as_date() ) %>%
full_join(temp) %>%
mutate(date_asnumeric= as.numeric(date_asdate) ) %>%
arrange(date_asnumeric) %>%
mutate(confirmed_nonmissing_count = (!is.na(confirmed)) %>% cumsum() ) %>%
mutate(deaths_nonmissing_count = (!is.na(deaths)) %>% cumsum() ) %>%
mutate(tested_people_nonmissing_count = (!is.na(tested_people)) %>% cumsum() ) %>%
mutate(tested_samples_nonmissing_count = (!is.na(tested_samples)) %>% cumsum() ) %>%
arrange(-date_asnumeric) %>%
mutate(confirmed_nonmissing_count_reversed = (!is.na(confirmed)) %>% cumsum() ) %>%
mutate(deaths_nonmissing_count_reversed = (!is.na(deaths)) %>% cumsum() ) %>%
mutate(tested_people_nonmissing_count_reversed = (!is.na(tested_people)) %>% cumsum() ) %>%
mutate(tested_samples_nonmissing_count_reversed = (!is.na(tested_samples)) %>% cumsum() ) %>%
arrange(date_asdate)
tryCatch({
if(sum(!is.na(temp$confirmed_log))>=3){ #need at least 3 points
tree_confirmed <- party::mob(confirmed_log ~ 1 + date_asnumeric | date_asnumeric , control = mob_control(minsplit = 3, alpha=.2), data = temp, model = linearModel) # + I(date_asnumeric^2)
temp$confirmed_log_y_hat <- predict( tree_confirmed, newdata=temp , type = c("response") )
temp$confirmed_log_group_number <- predict( tree_confirmed, newdata=temp , type = c("node"))
temp <- temp %>%
mutate(confirmed_log_y_hat =ifelse(confirmed_nonmissing_count>0 & confirmed_nonmissing_count_reversed>0,confirmed_log_y_hat,NA)) %>% #only interpolate within the observed data, never before or after
mutate(confirmed_log_group_number=ifelse(confirmed_nonmissing_count>0 & confirmed_nonmissing_count_reversed>0,confirmed_log_group_number,NA)) %>% #only interpolate within the observed data, never before or after
group_by(confirmed_log_group_number) %>%
arrange(date_asnumeric) %>%
mutate(confirmed_log_y_hat_slope=tsibble::difference(confirmed_log_y_hat)) %>%
fill(confirmed_log_y_hat_slope, .direction="up") %>%
ungroup() %>%
mutate(confirmed_log_y_hat_percent_change = round((exp(confirmed_log_y_hat_slope)-1)*100,2)) %>%
mutate(confirmed_log_y_hat=ifelse(confirmed_log_y_hat<0,NA, confirmed_log_y_hat))
}
}, error = function(e) {})
tryCatch({
if(sum(!is.na(temp$deaths_log))>=3){ #need at least 3 points
tree_deaths <- party::mob(deaths_log ~ 1 + date_asnumeric | date_asnumeric , control = mob_control(minsplit = 3, alpha=.2), data = temp, model = linearModel) # + I(date_asnumeric^2)
temp$deaths_log_y_hat <- predict( tree_deaths, newdata=temp , type = c("response") )
temp$deaths_log_group_number <- predict( tree_deaths, newdata=temp , type = c("node"))
temp <- temp %>%
mutate(deaths_log_y_hat=ifelse(deaths_nonmissing_count>0 & deaths_nonmissing_count_reversed>0,deaths_log_y_hat,NA)) %>% #only interpolate within the observed data, never before
mutate(deaths_log_group_number=ifelse(deaths_nonmissing_count>0 & deaths_nonmissing_count_reversed>0,deaths_log_group_number,NA)) %>% #only interpolate within the observed data, never before
group_by(deaths_log_group_number) %>%
arrange(date_asnumeric) %>%
mutate(deaths_log_y_hat_slope=tsibble::difference(deaths_log_y_hat)) %>%
fill(deaths_log_y_hat_slope, .direction="up") %>%
ungroup() %>%
mutate(deaths_log_y_hat_percent_change = round((exp(deaths_log_y_hat_slope)-1)*100,2)) %>%
mutate(deaths_log_y_hat=ifelse(deaths_log_y_hat<0,NA, deaths_log_y_hat)) #reject any where the prediction is less than 1 full case
}
}, error = function(e) {})
tryCatch({
if(sum(!is.na(temp$tested_people_log))>=3){ #need at least 3 points
tree_tested_people <- party::mob(tested_people_log ~ 1 + date_asnumeric | date_asnumeric , control = mob_control(minsplit = 3, alpha=.2), data = temp, model = linearModel) # + I(date_asnumeric^2)
temp$tested_people_log_y_hat <- predict( tree_tested_people, newdata=temp , type = c("response") )
temp$tested_people_log_group_number <- predict( tree_tested_people, newdata=temp , type = c("node"))
temp <- temp %>%
mutate(tested_people_log_y_hat=ifelse(tested_people_nonmissing_count>0 & tested_people_nonmissing_count_reversed>0,tested_people_log_y_hat,NA)) %>% #only interpolate within the observed data, never before
mutate(tested_people_log_group_number=ifelse(tested_people_nonmissing_count>0 & tested_people_nonmissing_count_reversed>0,tested_people_log_group_number,NA)) %>% #only interpolate within the observed data, never before
group_by(tested_people_log_group_number) %>%
arrange(date_asnumeric) %>%
mutate(tested_people_log_y_hat_slope=tsibble::difference(tested_people_log_y_hat)) %>%
fill(tested_people_log_y_hat_slope, .direction="up") %>% ungroup() %>%
mutate(tested_people_log_y_hat_percent_change = round((exp(tested_people_log_y_hat_slope)-1)*100,2)) %>%
mutate(tested_people_log_y_hat=ifelse(tested_people_log_y_hat<0,NA, tested_people_log_y_hat)) #reject any where the prediction is less than 1 full case
}
}, error = function(e) {})
temp_list1[[q ]] <- temp
})
}
lhs_long_clean_imputed1 <- bind_rows(temp_list1)
dim(lhs_long_clean_imputed1) #500,786 #bigger because we're interpolating now
#rt1 <- rpart(formula = confirmed_log_y_hat_percent_change ~ date_asnumeric, data=test)
#interpolated = data.frame(date_asnumeric=min(test$date_asnumeric):max(test$date_asnumeric) )
#interpolated$confirmed_log_y_hat_percent_change_y_hat <- predict(rt1, newdata=interpolated)
#interpolated$date_asdate <- as.Date(interpolated$date_asnumeric)
places <- lhs_long_clean %>% dplyr::select(gid_geonameid_wikidata_id) %>% distinct() %>% pull(gid_geonameid_wikidata_id)
library(rpart)
minsplit=6
minbucket=3
temp_list2 <- list()
for(q in places ){
print(q)
temp <- lhs_long_clean_imputed1 %>%
filter(gid_geonameid_wikidata_id %in% q) %>%
arrange(date_asnumeric)
tryCatch({
rt1 <- rpart::rpart(formula = confirmed_log_y_hat_percent_change ~ date_asnumeric,
data=temp %>% filter(!is.na(confirmed_log)), #to keep from fitting to interpolate slopes that are out of domain and usually wrong, require confirmed to not be missing or na
control = rpart.control(minsplit = minsplit, minbucket=minbucket))
temp$confirmed_log_y_hat_percent_change_y_hat <- predict(rt1, newdata=temp) #this prediction helpfully tries to impute backwards even before there are any day in any series
#We need to nuke it if no data exist
temp <- temp %>%
group_by(date_asdate) %>%
mutate( confirmed_nonmissing_count_datasets=sum(confirmed_nonmissing_count>0,na.rm=T) ) %>%
mutate( confirmed_nonmissing_count_datasets_reversed=sum(confirmed_nonmissing_count_reversed>0,na.rm=T) ) %>%
mutate(confirmed_log_y_hat_percent_change_y_hat=ifelse(confirmed_nonmissing_count_datasets>0 & confirmed_nonmissing_count_datasets_reversed>0,confirmed_log_y_hat_percent_change_y_hat,NA)) %>%
ungroup()
}, error = function(e) {})
tryCatch({
rt2 <- rpart::rpart(formula = deaths_log_y_hat_percent_change ~ date_asnumeric,
data=temp %>% filter(!is.na(deaths_log)),
control = rpart.control(minsplit = minsplit, minbucket=minbucket))
temp$deaths_log_y_hat_percent_change_y_hat <- predict(rt2, newdata=temp)
temp <- temp %>%
group_by(date_asdate) %>%
mutate( deaths_nonmissing_count_datasets=sum(deaths_nonmissing_count>0,na.rm=T) ) %>%
mutate( deaths_nonmissing_count_datasets_reversed=sum(deaths_nonmissing_count_reversed>0,na.rm=T) ) %>%
mutate(deaths_log_y_hat_percent_change_y_hat=ifelse(deaths_nonmissing_count_datasets>0 & deaths_nonmissing_count_datasets_reversed>0,deaths_log_y_hat_percent_change_y_hat,NA)) %>%
ungroup()
}, error = function(e) {})
tryCatch({
rt3 <- rpart::rpart(formula = tested_people_log_y_hat_percent_change ~ date_asnumeric,
data=temp %>% filter(!is.na(tested_people_log)),
control = rpart.control(minsplit = minsplit, minbucket=minbucket))
temp$tested_people_log_y_hat_percent_change_y_hat <- predict(rt3, newdata=temp, control = rpart.control(minsplit = minsplit, minbucket=minbucket))
temp <- temp %>%
group_by(date_asdate) %>%
mutate( tested_people_nonmissing_count_datasets=sum(tested_people_nonmissing_count>0,na.rm=T) ) %>%
mutate( tested_people_nonmissing_count_datasets_reversed=sum(tested_people_nonmissing_count_reversed>0,na.rm=T) ) %>%
mutate(tested_people_log_y_hat_percent_change_y_hat=ifelse(tested_people_nonmissing_count_datasets>0 & tested_people_nonmissing_count_datasets_reversed>0,tested_people_log_y_hat_percent_change_y_hat,NA)) %>%
ungroup()
}, error = function(e) {})
temp_list2[[q ]] <- temp
}
lhs_long_clean_imputed2 <- bind_rows(temp_list2)
lhs_long_clean_imputed <- lhs_long_clean_imputed2
dim(lhs_long_clean_imputed) #419910 #413475 #408,369 #we lose anywithout q codes here
saveRDS(lhs_long_clean_imputed, "/media/skynet2/905884f0-7546-4273-9061-12a790830beb/rwd_github_private/NESScovid19/data_temp/lhs_long_clean_imputed.Rds")
Examples
China
#China
#"Q148"
test <- lhs_long_clean_imputed %>%
mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q148") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation0 <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 Confirmed") + facet_wrap(~dataset )
Data on China shows variation across datasets for when they start measuring. Only two observe the very beginning of the outbreak. All of the datasets show a discontinuity where reporting standards must have changed. Our method attempts to bridge that gap in 3 of the series but not two others.
p_interpolation0

Italy
#Italy
#"Q38"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q38") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation1 <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 Confirmed") + facet_wrap(~dataset )
Italy likewise shows variation in the start of recording across datasets. There’s also variation in the initial sparcity. Wikipedia is strangely missing data in the middle. Our method linearly interpolates into that space in a way in a way we probably don’t want.
p_interpolation1

Italy
#US
#"Q30"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q30") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation2 <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("US Q30 Confirmed") + facet_wrap(~dataset )
p_interpolation2

New York State
#US
#"Q30"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q1384") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation3 <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("New York State Q1384 Confirmed") + facet_wrap(~dataset )
p_interpolation3

New York City (by county)
nyt has it just by city, it doesn’t break it down by the boroughs. But because gadm doesn’t do cities we don’t assign it a qcode.
usafacts has it as New York County which is New York County (Manhattan)
#Brooklyn (Q18419)
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q855974") %>% #no hits?
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation4a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bronx County (Q855974)") + facet_wrap(~dataset ) + guides( color = FALSE)
#Queens County, New York Q5142559
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q5142559") %>% #no hits?
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation4b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Queens County, New York Q5142559") + facet_wrap(~dataset ) + guides( color = FALSE)
#Brooklyn is aparently Kings County Q11980692
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q11980692") %>% #no hits?
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation4c <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Brooklyn is Kings County Q11980692") + facet_wrap(~dataset ) + guides( color = FALSE)
# Manhattan is New York County Q500416
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q500416") %>% #no hits?
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation4d <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Manhattan is New York County Q500416") + facet_wrap(~dataset ) + guides( color = FALSE)
#Staten Island is richmond county Q11997784
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q11997784") %>% #no hits?
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p_interpolation4e <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Staten Island Richmond County Q11997784") + facet_wrap(~dataset ) + guides( color = FALSE)
Note that CSSE is conflating all of New York City with Manhattan/New York County, Bing is too I think
p_interpolation4a + p_interpolation4b + p_interpolation4c + p_interpolation4d + p_interpolation4e

Interpolation of Rate of Change
Plot Confirmed Curves for Select Locations
library(patchwork)
lhs_long_clean_imputed <- readRDS( "/media/skynet2/905884f0-7546-4273-9061-12a790830beb/rwd_github_private/NESScovid19/data_temp/lhs_long_clean_imputed.Rds")
dim(lhs_long_clean_imputed) #45,609 #337043
#we want the colors to be consistent by dataset too btw
#####
#USA Q30
#bp_temp <- breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=temp_df %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q30"))
#confirmed_log_y_hat_percent_change=fitted.values(bp_temp)
test <- lhs_long_clean_imputed %>%
mutate(group=paste(dataset,wikidata_id,confirmed_log_group_number)) %>%
filter(wikidata_id=="Q30") %>%
arrange(date_asdate) %>%
mutate(date_asnumeric = date_asdate %>% as.numeric() )
#rt1 <- rpart(formula = confirmed_log_y_hat_percent_change ~ date_asnumeric, data=test)
#interpolated = data.frame(date_asnumeric=min(test$date_asnumeric):max(test$date_asnumeric) )
#interpolated$confirmed_log_y_hat_percent_change_y_hat <- predict(rt1, newdata=interpolated)
#interpolated$date_asdate <- as.Date(interpolated$date_asnumeric)
p0a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("USA Q30 Confirmed") # + facet_wrap(~dataset)
p0b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3 ) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black" ) +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("USA Q30 Confirmed") # + facet_wrap(~dataset)+ ylab("Daily Percent Change Confirmed")
#p0a / p0b
#####
#China Q148
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_group_number)) %>% filter(wikidata_id=="Q148") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
p1a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 Confirmed")
p1b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 Confirmed")+ ylab("Daily Percent Change Confirmed")
#p1a / p1b
#India
#"Q668"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q668") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p2a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("India Q668 Confirmed")
p2b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("India Q668 Confirmed")+ ylab("Daily Percent Change Confirmed")
#p2a / p2b
#Italy
#"Q38"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q38") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p4a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 Confirmed")
p4b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 Confirmed")+ ylab("Daily Percent Change Confirmed")
#p4a / p4b
#South Korea
#"Q884"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q884") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p5a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("South Korea Q884 Confirmed")
p5b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("South Korea Q884 Confirmed") + ylab("Daily Percent Change Confirmed")
#p5a / p5b
(p0a + p1a + p2a ) / (p0b + p1b + p2b )

( p4a + p5a) / ( p4b + p5b)

test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q1439") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p0a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Texas Q1439 Confirmed")
p0b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Texas Q1439 Confirmed") + ylim(0,100)+ ylab("Daily Percent Change Confirmed")
#Bexar
#"Q16861"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q16861") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p1a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bexar County Q16861 Confirmed")
p1b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bexar County Q16861 Confirmed") + ylim(0,100)+ ylab("Daily Percent Change Confirmed")
#California
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q99") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p2a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("California Q99 Confirmed")
p2b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("California Q99 Confirmed") + ylim(0,100)+ ylab("Daily Percent Change Confirmed")
#San Diego County (Q108143)
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q108143") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p3a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("San Diego County (Q108143) Confirmed")
p3b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("San Diego County (Q108143) Confirmed") + ylim(0,100)+ ylab("Daily Percent Change Confirmed")
#Florida (Q812)
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q812") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p4a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Florida (Q812) Confirmed")
p4b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Florida (Q812) Confirmed") + ylim(0,100)+ ylab("Daily Percent Change Confirmed")
#St. Lucie County (Q494564)
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,confirmed_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q494564") %>%
mutate(group=paste(dataset, wikidata_id,confirmed_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( confirmed_log_y_hat_percent_change = breakpoints(formula=confirmed_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p5a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=confirmed_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("St. Lucie County (Q494564) Confirmed")
p5b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=confirmed_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=confirmed_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=confirmed_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("St. Lucie County (Q494564) Confirmed") + ylim(0,100)+ ylab("Daily Percent Change Confirmed")
#Not counting slopes that were interpolated out of domain fixed california's plot
( p0a + p1a ) / ( p0b + p1b )

( p2a + p3a ) / ( p2b + p3b )

( p4a + p5a) / ( p4b + p5b)

Plot Death Curves for Select Locations
Show how interpolation works on deaths
test <- lhs_long_clean_imputed %>%
mutate(group=paste(dataset,wikidata_id,deaths_log_group_number)) %>%
filter(wikidata_id=="Q30") %>%
arrange(date_asdate) %>%
mutate(date_asnumeric = date_asdate %>% as.numeric() )
p0a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=deaths_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("USA Q30 Deaths") # + facet_wrap(~dataset)
p0b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=deaths_log_y_hat_percent_change, color=dataset), alpha=.3 ) +
geom_line(aes(x=date_asdate , y=deaths_log_y_hat_percent_change_y_hat ), alpha=1, color="black" ) +
#geom_smooth( aes(x=date_asdate , y=deaths_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("USA Q30 Deaths") + ylab("Daily Percent Change Deaths") # + facet_wrap(~dataset)
#p0a / p0b
#####
#China Q148
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,deaths_log_group_number)) %>% filter(wikidata_id=="Q148") %>%
mutate(group=paste(dataset, wikidata_id,deaths_log_group_number)) %>%
arrange(date_asdate) #%>%
p1a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=deaths_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 Deaths")
p1b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=deaths_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=deaths_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=deaths_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 Deaths")+ ylab("Daily Percent Change Deaths")
#p1a / p1b
#India
#"Q668"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,deaths_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q668") %>%
mutate(group=paste(dataset, wikidata_id,deaths_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( deaths_log_y_hat_percent_change = breakpoints(formula=deaths_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p2a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=deaths_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("India Q668 Deaths")
p2b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=deaths_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=deaths_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=deaths_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("India Q668 Deaths")+ ylab("Daily Percent Change Deaths")
#p2a / p2b
#Bexar
#"Q16861"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,deaths_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q16861") %>%
mutate(group=paste(dataset, wikidata_id,deaths_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( deaths_log_y_hat_percent_change = breakpoints(formula=deaths_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p3a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=deaths_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bexar County Q16861 Deaths")
p3b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=deaths_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=deaths_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=deaths_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bexar County Q16861 Deaths") + ylim(0,100)+ ylab("Daily Percent Change Deaths")
#p3a / p3b
#Italy
#"Q38"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,deaths_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q38") %>%
mutate(group=paste(dataset, wikidata_id,deaths_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( deaths_log_y_hat_percent_change = breakpoints(formula=deaths_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p4a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=deaths_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 Deaths")
p4b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=deaths_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=deaths_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=deaths_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 Deaths")+ ylab("Daily Percent Change Deaths")
#p4a / p4b
#South Korea
#"Q884"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,deaths_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q884") %>%
mutate(group=paste(dataset, wikidata_id,deaths_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( deaths_log_y_hat_percent_change = breakpoints(formula=deaths_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p5a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=deaths_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("South Korea Q884 Deaths")
p5b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=deaths_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=deaths_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=deaths_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=deaths_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("South Korea Q884 Deaths") + ylab("Daily Percent Change Deaths")
#p5a / p5b
I need to fix this, USA has a fraction of a death
Note the discontinuity in Chin when they added those 1k deaths to the total
India deaths is broken, we shouldn’t be interpolating a rate before we think the number is greater than 0
(p0a + p1a + p2a ) / (p0b + p1b + p2b )

(p3a + p4a + p5a) / (p3b + p4b + p5b)

Plot Testing Curves for Select Locations
Show how interpolation works on tested
US is an example where we interpolated past our available data. Shouldn’t do that either!
test <- lhs_long_clean_imputed %>%
mutate(group=paste(dataset,wikidata_id,tested_people_log_group_number)) %>%
filter(wikidata_id=="Q30") %>%
arrange(date_asdate) %>%
mutate(date_asnumeric = date_asdate %>% as.numeric() )
p0a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=tested_people_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("USA Q30 Tested") #+ facet_wrap(~dataset)
p0b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change, color=dataset), alpha=.3 ) +
geom_line(aes(x=date_asdate , y=tested_people_log_y_hat_percent_change_y_hat ), alpha=1, color="black" ) +
#geom_smooth( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("USA Q30 tested_people") + ylab("Daily Percent Change tested_people") # + facet_wrap(~dataset)
#p0a / p0b
#####
#China Q148
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,tested_people_log_group_number)) %>% filter(wikidata_id=="Q148") %>%
mutate(group=paste(dataset, wikidata_id,tested_people_log_group_number)) %>%
arrange(date_asdate) #%>%
p1a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=tested_people_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 tested_people")
p1b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=tested_people_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("China Q148 tested_people")+ ylab("Daily Percent Change tested_people")
#p1a / p1b
#India
#"Q668"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,tested_people_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q668") %>%
mutate(group=paste(dataset, wikidata_id,tested_people_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( tested_people_log_y_hat_percent_change = breakpoints(formula=tested_people_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p2a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=tested_people_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("India Q668 tested_people")
p2b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=tested_people_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("India Q668 tested_people")+ ylab("Daily Percent Change tested_people")
#p2a / p2b
#Bexar
#"Q16861"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,tested_people_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q16861") %>%
mutate(group=paste(dataset, wikidata_id,tested_people_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( tested_people_log_y_hat_percent_change = breakpoints(formula=tested_people_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p3a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=tested_people_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bexar County Q16861 tested_people")
p3b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=tested_people_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Bexar County Q16861 tested_people") + ylim(0,100)+ ylab("Daily Percent Change tested_people")
#p3a / p3b
#Italy
#"Q38"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,tested_people_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q38") %>%
mutate(group=paste(dataset, wikidata_id,tested_people_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( tested_people_log_y_hat_percent_change = breakpoints(formula=tested_people_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p4a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=tested_people_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 tested_people")
p4b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=tested_people_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("Italy Q38 tested_people")+ ylab("Daily Percent Change tested_people")
#p4a / p4b
#South Korea
#"Q884"
test <- lhs_long_clean_imputed %>% mutate(group=paste(dataset,wikidata_id,tested_people_log_y_hat_percent_change)) %>% filter(wikidata_id=="Q884") %>%
mutate(group=paste(dataset, wikidata_id,tested_people_log_group_number)) %>%
arrange(date_asdate) #%>%
#mutate( tested_people_log_y_hat_percent_change = breakpoints(formula=tested_people_log_y_hat_percent_change ~ 1, data=. ) %>% fitted.values() )
p5a <- test %>%
ggplot() +
geom_point( aes(x=date_asdate, y=tested_people_log, color=dataset), alpha=.3) +
geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("South Korea Q884 tested_people")
p5b <- test %>%
ggplot() +
geom_point( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change, color=dataset), alpha=.3) +
geom_line(aes(x=date_asdate , y=tested_people_log_y_hat_percent_change_y_hat ), alpha=1, color="black") +
#geom_smooth( aes(x=date_asdate , y=tested_people_log_y_hat_percent_change), alpha=.3, span=.05) + #, span=.05
#geom_line( aes(x=date_asdate, y=tested_people_log_y_hat, color=dataset, group=group)) + #
#geom_line(data=temp_df2, aes(x=date_asdate, y=y_hat_mean), color="black", linetype = "dashed") +
theme_bw() +
ggtitle("South Korea Q884 tested_people") + ylab("Daily Percent Change tested_people")
#p5a / p5b
I need to fix this, USA has a fraction of a death
Note the discontinuity in Chin when they added those 1k deaths to the total
India deaths is broken, we shouldn’t be interpolating a rate before we think the number is greater than 0
(p0a + p1a + p2a ) / (p0b + p1b + p2b )

(p3a + p4a + p5a) / (p3b + p4b + p5b)

Aligning Curves by Takeoff
library(infotheo)
#Once we removed the no variance places my alignment has more mutual information than either first confirmed or 100 confirmed
mutinformation(X=df_slopes %>% dplyr::select(t,t_alligned,t_alligned_firstconfirmed,confirmed_log_y_hat_percent_change_y_hat) %>% discretize(), method="emp") #we outperformed t_alligned_100confirmed but it wasn't avail for most
#df_slopes %>% filter(abs(t_alligned)<20,abs(t_alligned_100confirmed_100)<20) %>% janitor::tabyl(t_alligned, t_alligned_100confirmed_100)
#hist(df_slopes$t_alligned - df_slopes$t_alligned_100confirmed_100, breaks=50)
Plot of curves raw and then curves alligned by takeoff start
The idea here is that completely unconstrained, COVID-19 growth should follow a logistic curve, flat, upswing, constant growth, downswing, and flat again. The assumption of no unconstrained growth no longer holds because the world is reacting, but there’s still a pretty uniformly characteristic upswing across geographic units. We look for this signal of the largest first difference in the daily percent change, call that the takeoff date, and then allign all the time series with that date as 0.
p_t_alligned_firstconfirmed / p_t_alligned

What this gives us is a nice normalized dataset where the task is to predict the shape of that distribution. We could try to predict time until the takeoff, the intensity of the growth at the takeoff point, the time until it returns to zero, the area under the curve, or every nook and change.
lhs_long_median %>% ggplot(aes(x=date_asdate, y=confirmed, color=wikidata_id)) + geom_line() + theme(legend.position = "none")
lhs_long_median %>% ggplot(aes(x=date_asdate, y=deaths, color=wikidata_id)) + geom_line() + theme(legend.position = "none")
lhs_long_median %>% ggplot(aes(x=date_asdate, y=deaths, color=wikidata_id)) + geom_line() + theme(legend.position = "none") + scale_y_log10()
library(tsibble)
lhs_long_median %>% arrange(wikidata_id,date_asdate) %>%
group_by(wikidata_id) %>%
mutate(deaths_fd=tsibble::difference(deaths)) %>%
ungroup() %>%
filter(deaths_fd>0) %>%
ggplot(aes(x=date_asdate, y=deaths_fd, color=wikidata_id)) +
geom_line() +
#stat_smooth(method="loess", se = F) +
theme(legend.position = "none") # + scale_y_log10()
lm1 <- lm(deaths ~ confirmed,data=lhs_long_median %>% filter(CFR<1))
lm2 <- lm(deaths ~ tested_people + confirmed,data=lhs_long_median %>% filter(CFR<1))
library(ggRandomForests); #install.packages('ggRandomForests')
rf1 <- rfsrc(deaths~ confirmed,
data=lhs_long_median %>% filter(CFR<1) %>% as.data.frame() )
gg_e <- gg_error(rf1)
gg_v <- gg_variable(rf1)
plot(gg_v, panel=TRUE, se=.95, span=1.2, alpha=.4)
rf1 <- rfsrc(deaths~ confirmed + tested_people,
data=lhs_long_median %>% filter(CFR<1) %>% as.data.frame() )
gg_e <- gg_error(rf1)
gg_v <- gg_variable(rf1)
plot(gg_v, panel=TRUE, se=.95, span=1.2, alpha=.4)
rf2 <- rfsrc(CFR ~ tested_people_log,
data=lhs_long_median %>%
mutate(CFR=deaths/confirmed) %>%
mutate(tested_people_log=log(tested_people+1)) %>%
filter(CFR<1) %>% as.data.frame()
)
gg_v <- gg_variable(rf2)
plot(gg_v, panel=TRUE, se=.95, span=1.2, alpha=.4)
rf2 <- rfsrc(CFR ~ tested_people_log + confirmed_log,
data=lhs_long_median %>%
mutate(CFR=deaths/confirmed) %>%
mutate(tested_people_log=log(tested_people+1)) %>%
mutate(confirmed_log=log(confirmed+1)) %>%
filter(CFR<1) %>% as.data.frame()
)
gg_v <- gg_variable(rf2)
plot(gg_v, panel=TRUE, se=.95, span=1.2, alpha=.4)
#Throw in time
rf3 <- rfsrc(CFR ~ positive_perc + tested_people_log,
data=lhs_long_median %>%
mutate(CFR=deaths/confirmed) %>%
mutate(positive_perc=confirmed/tested_people) %>%
mutate(tested_people_log=log(tested_people+1)) %>%
mutate(confirmed_log=log(confirmed+1)) %>%
filter(CFR<1) %>% as.data.frame()
)
gg_v <- gg_variable(rf3)
plot(gg_v, panel=TRUE, se=.95, span=1.2, alpha=.4)
partial_Boston <- plot.variable(rf3,
partial=TRUE, sorted=FALSE,
show.plots = FALSE )
gg_p <- gg_partial(partial_Boston)
plot(gg_p, panel=TRUE, points = F )
copper_cts <-quantile_pts(lhs_long_median$tested_people_log, groups = 6, intervals = TRUE)
partial_coplot_Boston <- gg_partial_coplot(rf2, xvar="confirmed_log",
groups=rm_grp,
show.plots=FALSE)
summary(lhs_long_median$CFR)
lhs_long_median %>% filter(confirmed>10) %>% filter(CFR<1) %>% pull(CFR) %>% summary() #0.0297297 that's a median CFR of about 3%
lhs_long_median %>% filter(confirmed>10) %>% filter(CFR<1) %>% pull(CFR) %>% hist(breaks=50)
lhs_long_median %>% filter(confirmed>10) %>% filter(CFR<1) %>% ggplot(aes(x=CFR)) + geom_density()
#This code is now depricated in favor of the tree base method above
places <- lhs_long_clean$wikidata_id %>% unique() %>% na.omit() ; length(places)
datasets <- lhs_long_clean$dataset %>% unique() %>% na.omit() ; table(dataset)
temp_list <- list()
for(p in places){
print(p)
for(d in datasets){
temp <- NULL
temp <- lhs_long_clean %>%
arrange(date_asdate) %>%
filter(dataset %in% d) %>%
filter(wikidata_id %in% p) %>%
mutate(confirmed_log=log(confirmed+1)) %>%
mutate(deaths_log=log(deaths+1)) %>%
mutate(tested_people_log=log(tested_people+1)) %>%
mutate(t= as.numeric(date_asdate) - min(as.numeric(date_asdate)) +1 ) %>% #start at 1 to make indexing easier
mutate(i= row_number() ) # actually need this
i_original <- temp$i
if( nrow(temp)==0 ) { next} #print("error");
print(p)
#bp <- breakpoints(confirmed_log ~ 1, data=temp)
bp <- NULL
lm1 <- NULL
y_hat <- NA
cdf <- NULL
try({
#if it fails fall back to just a lm
lm1 <- lm(confirmed_log ~ 1 + t, data=temp)
cdf <- data.frame(
t= 1,
confirmed_log_intercept= coef(lm1)[1],
confirmed_log_slope= coef(lm1)[2],
confirmed_log_slope_break=0
)
confirmed_log_y_hat=fitted.values(lm1)
})
try({
bp <- breakpoints(confirmed_log ~ 1 + t, data=temp, h=3)
cdf <- data.frame(
i= c(1,bp$breakpoints),
confirmed_log_intercept= coef(bp)[,1],
confirmed_log_slope= coef(bp)[,2],
confirmed_log_slope_break=1
)
confirmed_log_y_hat=fitted.values(bp)
})
try({
temp2 <- temp
temp2$confirmed_log_y_hat <- NA
temp2$confirmed_log_y_hat <- confirmed_log_y_hat
temp2 <- temp2 %>%
left_join(cdf)
q=paste0(p,"_",d)
temp2 <- temp2 %>%
expand(dataset, gid,geonameid, wikidata_id,t=min(temp$t):max(temp$t)) %>% #expand this to include all the t
left_join(temp2) %>%
mutate(date_asdate=min(date_asdate, na.rm=T)-1+t) %>% #go back interp date again
mutate(confirmed_log_slope_break = confirmed_log_slope_break %>% replace_na(0) %>% cumsum() ) %>%
fill(confirmed_log_intercept) %>%
fill(confirmed_log_slope) %>%
mutate(confirmed_log_y_hat= confirmed_log_intercept + confirmed_log_slope*t ) %>%
mutate(confirmed_log_slope_percent_change = round((exp(confirmed_log_slope)-1)*100,2))
temp_list[[as.character(q)]] <- temp2
})
#if( is.na( temp_list[[as.character(q)]]$y_hat) ) {print("error"); break}
}
}
#"13055"
temp_df <- bind_rows(temp_list)
dim(temp_df) #bigger because we're interpolating now
# install.packages("devtools")
#devtools::install_github("tidyverse/multidplyr")
library(multidplyr)
library(dplyr, warn.conflicts = FALSE)
#cluster <- new_cluster(4)
#need to supress messages
rex_function <- function(x){
temp=data.frame(confirmed_log_slope=x)
tryCatch({
#if there's an NA in x we get an error because breakpoints is one short
prediction <- breakpoints(formula=confirmed_log_slope ~ 1, data=temp, h=3) %>% fitted.values()
result=rep(NA, length(x) )
result[!is.na(x)] <-prediction
return(result)
}, error=function(e){})
return( rep(NA, length(x) ) )
}
#didn't take too long now
#library(multidplyr)
#library(dplyr, warn.conflicts = FALSE)
#cluster <- new_cluster(4)
library(tictoc)
tic()
library(strucchange)
test <- temp_df %>% head(20000)
test3 <- test %>%
group_by(wikidata_id) %>%
#partition(cluster) %>%
arrange(date_asdate) %>%
#mutate( confirmed_log_slope_y_hat = breakpoints(formula=confirmed_log_slope ~ 1, data=. ) %>% fitted.values() ) %>%
mutate( confirmed_log_slope_y_hat = rex_function(confirmed_log_slope) ) %>% #fails on the cluster
ungroup() #%>%
#collect()
toc() #48 seconds for 10k #122 seconds for 20k
saveRDS(temp_df, "/media/skynet2/905884f0-7546-4273-9061-12a790830beb/rwd_github_private/NESScovid19/data_temp/lhs_long_interpolated.Rds")
LS0tCnRpdGxlOiAiVGhlIE1hY2hpbmUgTGVhcm5pbmcgZm9yIFNvY2lhbCBTY2llbmNlIEdsb2JhbCBTdWJuYXRpb25hbCBDb3ZpZCBDb3VudHMgRGF0c2V0IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQpkYXRlOiAKYXV0aG9yOiAKYWZmaWxpYXRpb246IERpcmVjdG9yLCBNYWNoaW5lIExlYXJuaW5nIGZvciBTb2NpYWwgU2NpZW5jZSBMYWIsIENlbnRlciBmb3IgUGVhY2UgYW5kIFNlY3VyaXR5IFN0dWRpZXMsIFVuaXZlcnNpdHkgb2YgQ2FsaWZvcm5pYSBTYW4gRGllZ28KZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgpSZXggVy4gRG91Z2xhc3MKCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJsb2NrcXVvdGUgewogICAgcGFkZGluZzogMTBweCAyMHB4OwogICAgbWFyZ2luOiAwIDAgMjBweDsKICAgIGZvbnQtc2l6ZTogMTRweDsKICAgIGJvcmRlci1sZWZ0OiA1cHggc29saWQgI2VlZTsKfQo8L3N0eWxlPgoKIyBJbnRyb2R1Y3Rpb24KCiMjIExpYnJhcnkgTG9hZHMKCmBgYHtyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CiNsaWJyYXJpZXMKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkodGlkeXZlcnNlKQoKI2RldnRvb2xzOjppbnN0YWxsX2dpdGh1Yigicm9wZW5zY2kvVVNBYm91bmRhcmllcyIpCiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInJvcGVuc2NpL1VTQWJvdW5kYXJpZXNEYXRhIikKbGlicmFyeShVU0Fib3VuZGFyaWVzKSA7ICNpbnN0YWxsLnBhY2thZ2VzKCdVU0Fib3VuZGFyaWVzJykKZGF0YShzdGF0ZV9jb2RlcykKCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShnZ2hpZ2hsaWdodCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoUjApICAjIGNvbnNpZGVyIG1vdmluZyBhbGwgbGlicmFyeSBjb21tYW5kcyB0byB0b3AgLS0gdGhpcyBvbmUgd2FzIGluIGEgbG9vcCBiZWxvdwoKbGlicmFyeShXaWtpZGF0YVIpCmxpYnJhcnkoY291bnRyeWNvZGUpCgpsaWJyYXJ5KHVzbWFwKSA7ICMgaW5zdGFsbC5wYWNrYWdlcygndXNtYXAnKQpkYXRhKHN0YXRlcG9wKQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJyb3BlbnNjaS9VU0Fib3VuZGFyaWVzIikKI2RldnRvb2xzOjppbnN0YWxsX2dpdGh1Yigicm9wZW5zY2kvVVNBYm91bmRhcmllc0RhdGEiKQpsaWJyYXJ5KFVTQWJvdW5kYXJpZXMpIDsgI2luc3RhbGwucGFja2FnZXMoJ1VTQWJvdW5kYXJpZXMnKQpkYXRhKHN0YXRlX2NvZGVzKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCgpsaWJyYXJ5KGpzb25saXRlKQoKI1RoaXMgaXMgdG9vIHNsb3cgaXQncyBkb3dubG9hZGluZyBlYWNoCmxpYnJhcnkoR0FETVRvb2xzKQpsaWJyYXJ5KHN0cnVjY2hhbmdlKSA7ICNpbnN0YWxsLnBhY2thZ2VzKCdzdHJ1Y2NoYW5nZScpCmxpYnJhcnkodHNpYmJsZSkKCmxpYnJhcnkocGF0Y2h3b3JrKQoKYGBgCiMjIERhdGEgTG9hZGluZyBhbmQgQ2xlYW5pbmcKCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9OCx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQoKbGlicmFyeSh0c2liYmxlKQoKbGhzX2xvbmcgPC0gcmVhZFJEUygiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvbGhzX2xvbmcuUmRzIikKI2RpbShsaHNfbG9uZykgIzE4NywzMDUKCmxoc19sb25nX2NsZWFuIDwtIGxoc19sb25nICU+JQogICAgICAgICAgICAgICAgICBtdXRhdGUoZGF0YXNldF9naWRfZ2VvbmFtZWlkX3dpa2lkYXRhX2lkPSBwYXN0ZShkYXRhc2V0LGdpZCxnZW9uYW1laWQsIHdpa2lkYXRhX2lkLCBzZXA9Il8iKSAgKSAlPiUKICAgICAgICAgICAgICAgICAgbXV0YXRlKGdpZF9nZW9uYW1laWRfd2lraWRhdGFfaWQ9IHBhc3RlKGdpZCxnZW9uYW1laWQsIHdpa2lkYXRhX2lkLCBzZXA9Il8iKSAgKSAlPiUKICAKICAgICAgICAgICAgICAgICAgZmlsdGVyKCFpcy5uYShkYXRlX2FzZGF0ZSkpICU+JQogICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgI0ZpcnN0IGRyb3AgYW55dGhpbmcgdGhhdCdzIG5lZ2F0aXZlLiBTaG91bGRuJ3QgYmUgYW55IG5lZ2F0aXZlcy4KICAgICAgICAgICAgICAgICAgZmlsdGVyKGlzLm5hKGNvbmZpcm1lZCkgfCBjb25maXJtZWQ+PTApICU+JQogICAgICAgICAgICAgICAgICBmaWx0ZXIoaXMubmEoZGVhdGhzKSB8IGRlYXRocz49MCkgJT4lCiAgICAgICAgICAgICAgICAgIGZpbHRlcihpcy5uYSh0ZXN0ZWRfcGVvcGxlKSB8IHRlc3RlZF9wZW9wbGU+PTApICU+JQogICAgICAgICAgICAgICAgICBmaWx0ZXIoaXMubmEodGVzdGVkX3NhbXBsZXMpIHwgdGVzdGVkX3NhbXBsZXM+PTApICU+JQogICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgI1RoZW4gc2V0IDBzIHRvIE5BLCB3ZSBkb24ndCB0cnVzdCBOQXMKICAgICAgICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZD1pZmVsc2UoY29uZmlybWVkPT0wLCBOQSwgY29uZmlybWVkKSkgJT4lCiAgICAgICAgICAgICAgICAgIG11dGF0ZShkZWF0aHM9aWZlbHNlKGRlYXRocz09MCwgTkEsIGRlYXRocykpICU+JQogICAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3Blb3BsZT1pZmVsc2UodGVzdGVkX3Blb3BsZT09MCwgTkEsIHRlc3RlZF9wZW9wbGUpKSAlPiUKICAgICAgICAgICAgICAgICAgbXV0YXRlKHRlc3RlZF9zYW1wbGVzPWlmZWxzZSh0ZXN0ZWRfc2FtcGxlcz09MCwgTkEsIHRlc3RlZF9zYW1wbGVzKSkgJT4lCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgI1RoZW4gY2hlY2sgZmlyc3QgZGlmZmVyZW5jZXMgYW5kIGRyb3AgYW55dGhpbmcgdGhhdCBkb2Vzbid0IHdlYWtseSBpbmNyZWFzZSBtb25vdG9uaWNhbGx5CiAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KGRhdGFzZXQsIGdpZF9nZW9uYW1laWRfd2lraWRhdGFfaWQpICU+JSAKICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAlPiUKICAgICAgICAgICAgICAgICAgICBtdXRhdGUoY29uZmlybWVkX2N1bW1heD1jb25maXJtZWQgJT4lIHJlcGxhY2VfbmEoMCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1bW1heCgpLCBkZWF0aHNfY3VtbWF4PWRlYXRocyU+JSByZXBsYWNlX25hKDApICU+JSBjdW1tYXgoKSwgdGVzdGVkX3Blb3BsZV9jdW1tYXg9dGVzdGVkX3Blb3BsZSU+JSByZXBsYWNlX25hKDApICU+JSBjdW1tYXgoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdGVkX3NhbXBsZXNfY3VtbWF4PXRlc3RlZF9zYW1wbGVzJT4lIHJlcGxhY2VfbmEoMCkgJT4lIGN1bW1heCgpKSAlPiUKICAgICAgICAgICAgICAgICAgdW5ncm91cCgpICU+JSAgCiAgCiAgICAgICAgICAgICAgICAgICNBYm91dCA0ayBvZiB0aGVzZSBvYnNlcnZhdGlvbnMgc2hvdyBhIGRlY3JlYXNlIGZyb20gb25lIHRpbWUgc3RlcCB0byB0aGUgbmV4dCB3aGljaCBzdWdnZXN0cyBlaXRoZXIgYW4gb3JpZ2luYWwgZXJyb3Igb3IgYSBqb2luaW5nIGVycm9yCiAgICAgICAgICAgICAgICAgICNXZSdyZSBnb2luZyB0byBzdHJhaWdodCBkcm9wIHRob3NlIG9ic2VydmF0aW9ucyBhcyBhIGNsZWFuaW5nIHN0ZXAKICAgICAgICAgICAgICAgICAgI3RoaXMgaXNuJ3QgZW5vdWdoIGJlY2F1c2UgaWYgeW91IGhhdmUgY29uc2VjdXRpdmUgbWlzdGFrZXMgaXQnbGwgc2hvdyBhIHBvc2l0aXZlIGZkIGV2ZW4gaWYgaXQncyBub3QgZ29vZCBlbm91Z2gKICAgICAgICAgICAgICAgICAgZmlsdGVyKCAoaXMubmEoY29uZmlybWVkKSB8IGNvbmZpcm1lZD49Y29uZmlybWVkX2N1bW1heCkgJiAgI25ldmVyIGFsbG93IGZvciBhIHJldmVyc2FsCiAgICAgICAgICAgICAgICAgICAgICAgICAgKGlzLm5hKGRlYXRocykgfCBkZWF0aHM+PWRlYXRoc19jdW1tYXgpICYgICAgICAgICNuZXZlciBhbGxvdyBmb3IgYSByZXZlcnNhbAogICAgICAgICAgICAgICAgICAgICAgICAgIChpcy5uYSh0ZXN0ZWRfcGVvcGxlKSB8IHRlc3RlZF9wZW9wbGU+PXRlc3RlZF9wZW9wbGVfY3VtbWF4KSAmICAjbmV2ZXIgYWxsb3cgZm9yIGEgcmV2ZXJzYWwKICAgICAgICAgICAgICAgICAgICAgICAgICAoaXMubmEodGVzdGVkX3NhbXBsZXMpIHwgdGVzdGVkX3NhbXBsZXM+PXRlc3RlZF9zYW1wbGVzX2N1bW1heCkgICNuZXZlciBhbGxvdyBmb3IgYSByZXZlcnNhbAogICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lCiAgI3dlJ3JlIGdvaW5nIHRvIGdvIG9uZSBzdGVwIGZ1cnRoZXIgYW5kIHJlcXVpcmUgZWl0aGVyIGNvbmZpcm1lZCBvciB0ZXN0ZWQgdG8gYmUgc3RyaWN0bHkgaGlnaGVyCiAgI0luIHdvcmRzLCBkdXJpbmcgYW4gZXBpc29kZSB3ZSBkb24ndCBiZWxpZXZlIHJlcG9ydHMgbWVhbiAibm8gbmV3IGNhc2VzIiBqdXN0IG5vIG5ldyBnb29kIHJlcG9ydGluZwogICNtZXRhYmlvdGEgaXMgdGhlIHdvcnN0IG9mZmVuZGVyIGhlcmUgc28gcmVzdHJpY3RpbmcgaXQgdG8ganVzdCB0aGF0CiAgZmlsdGVyKCAhKAogICAgICAgICAgICBkYXRhc2V0PT0ibWV0YWJpb3RhIiAmICNpcyBtZXRhYmlvdGEKICAgICAgICAgICAgKCFpcy5uYShjb25maXJtZWQpICYgICAjd2l0aCBhIG5vbiBtaXNzaW5nIGNvbmZpcm1lZAogICAgICAgICAgICAgIGNvbmZpcm1lZDw9Y29uZmlybWVkX2N1bW1heCApICN0aGF0IGlzIGVxdWFsIHRvIG9yIGxlc3MgdGhhbiB0aGUgY3VtdWxhdGl2ZSBtYXggdW50aWwgdGhlbi4KICAgICAgICAgICAgKSAjcmVqZWN0IHRoZXNlCiAgICAgICAgICApICU+JSAjbWV0YWJpb3RhIGlzIHJlYWxseSBwcm9ibGVtYXRpYyA5MCUgb2Ygd2hhdCB3ZSdyZSBkb2luZyBpcyB0cnlpbmcgdG8gYWNjb3VudCBmb3IgaXQKICAKICAjQWxzbyByZWplY3QgYW55IHdoZXJlIGRlYXRocyBhcmUgZ3JlYXRlciB0aGFuIGNvbmZpcm1lZAogIGZpbHRlcihpcy5uYShjb25maXJtZWQpIHwgaXMubmEoZGVhdGhzKSB8IGNvbmZpcm1lZD49ZGVhdGhzKSAlPiUKICAKICAjYWxzbyByZWplY3QgYW55IHdoZXJlIGNvbmZpcm1lZCBkb2Vzbid0IHZhcnkgCiAgZ3JvdXBfYnkoZ2lkICwgIGdlb25hbWVpZCAsd2lraWRhdGFfaWQpICU+JSAjY2hvc2Ugbm90IHRvIGRvIGJ5IGRhdGFzZXQgYmVjYXVzZSB0ZXN0aW5nIGRhdGFzZXRzIG1pZ2h0IG5vdCBoYXZlIGNvbmZpcm1lZAogICAgZmlsdGVyKHZhcihjb25maXJtZWQsIG5hLnJtPVQpPjApICU+JQogIHVuZ3JvdXAoKQoKICAKI2RpbShsaHNfbG9uZ19jbGVhbikgIzI4MSw0NjQgIzI5Miw1ODAgIzI5OTIxMyAjMTgxLDU2MwoKc2F2ZVJEUyhsaHNfbG9uZ19jbGVhbiwKICAgICAgICAiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvbGhzX2xvbmdfY2xlYW5kLlJkcyIpCgpgYGAKClN1bW1hcnkgU3RhdGlzdGljcyBvZiBPdXIgRGF0YQoKYGBge3J9CnByaW50KCJOdW1iZXIgb2Ygb2JzZXJ2YXRpb25zIikKZGltKGxoc19sb25nX2NsZWFuKQoKcHJpbnQoIk51bWJlciBvZiBsb2NhdGlvbnMiKQpsaHNfbG9uZ19jbGVhbiR3aWtpZGF0YV9pZCAlPiUgdW5pcXVlKCkgJT4lIGxlbmd0aCgpICMzLDM3MwoKcHJpbnQoIk51bWJlciBvZiBEYXlzIikKbGhzX2xvbmdfY2xlYW4kZGF0ZV9hc2RhdGUgJT4lIHVuaXF1ZSgpICU+JSBsZW5ndGgoKSAjMTEzCgpsaWJyYXJ5KERUKSAjaHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9EVC8KbGhzX2xvbmdfY2xlYW4gJT4lIGNvdW50KGRhdGFzZXQpICU+JSBhcnJhbmdlKC1uKSAlPiUgRFQ6OmRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMjAsIGF1dG9XaWR0aCA9IFRSVUUpKQoKI2xpYnJhcnkoZ3QpCiNsaHNfbG9uZ19jbGVhbiAlPiUgY291bnQoZGF0YXNldCkgJT4lIGFycmFuZ2UoLW4pICU+JSBndCgpICU+JSAKIyB0YWJfaGVhZGVyKAojICAgIHRpdGxlID0gbWQoIkxvY2F0aW9uLURheXMgYnkgRGF0YXNldCIpIywKIyAgICAjc3VidGl0bGUgPSAiTnVtYmVyIG9mIERheXMgd2l0aCBEYXRhIGJ5IERhdGFzZXQiCiMgICkgJT4lCiMgIGZtdF9taXNzaW5nKCBjb2x1bW5zPWV2ZXJ5dGhpbmcoKSwgcm93cz1OVUxMLG1pc3NpbmdfdGV4dCA9IDApCgpgYGAKCgojIFNwYXRpYWwgVmFyaWF0aW9uIGluIERhdGEgQXZhaWxhYmlsaXR5CgojIyBDb3VudHJ5IExldmVsIERhdGEgQXZhaWxhYmlsaXR5CgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CgojZ2FkbTM2ID0gc3RfcmVhZCgiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTZ2FkbS9kYXRhX2luL2dhZG0zNl9ncGtnL2dhZG0zNi5ncGtnIikKI3N0X2xheWVycygiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvZ2FkbTM2X2J5Y291bnRyeS9nYWRtMzZfbGV2ZWxzX2dwa2cvZ2FkbTM2X2xldmVscy5ncGtnIikKZ2FkbTM2X2xldmVsc18wID0gc3RfcmVhZCgiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvZ2FkbTM2X2J5Y291bnRyeS9nYWRtMzZfbGV2ZWxzX2dwa2cvZ2FkbTM2X2xldmVscy5ncGtnIiwgbGF5ZXI9ImxldmVsMCIpICAlPiUKICAgICAgICAgICAgICAgICAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IEZBTFNFLCBkVG9sZXJhbmNlID0wLjEpICMgIDAuMDI1IHRoaXMgaXMgc3VwcG9zZWRseSBicm9rZW4gdXAgYnkgNiBsZXZlbHMgYW5kIHNvIHNob3VsZCBoYXZlIHUucy4gCgojcGxvdChnYWRtMzZfbGV2ZWxzXzApCiNkaW0oZ2FkbTM2X2xldmVsc18wX3NmJHNmKQojZ2FkbV9wbG90KGdhZG0zNl9sZXZlbHNfMF9zZikKbGhzX2xvbmdfcGxhY2Vfc291cmNlcyA8LSBsaHNfbG9uZyAgJT4lIGRwbHlyOjpzZWxlY3QoZ2lkLCAgIGdlb25hbWVpZCwgd2lraWRhdGFfaWQsIGRhdGFzZXQpICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoZ2lkLCAgZ2VvbmFtZWlkLCB3aWtpZGF0YV9pZCkgJT4lIGNvdW50KGRhdGFzZXQpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShnaWQsICBnZW9uYW1laWQsIHdpa2lkYXRhX2lkKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKGRhdGFzZXRzX249bigpKSAKCnAwIDwtIGdhZG0zNl9sZXZlbHNfMCAlPiUgCiAgICAgIGxlZnRfam9pbihsaHNfbG9uZ19wbGFjZV9zb3VyY2VzICU+JSBkcGx5cjo6c2VsZWN0KGdpZD1naWQsIGRhdGFzZXRzX24pICU+JSAgbGVmdF9qb2luKCBnYWRtMzZfbGV2ZWxzXzAgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgZHBseXI6OnNlbGVjdChnaWQ9R0lEXzAsIE5BTUVfMCkgICU+JSBkaXN0aW5jdCgpICApCiAgICAgICAgICAgICAgICApICU+JQogICAgICAjcmVwbGFjZV9uYShsaXN0KGRhdGFzZXRzX24gPSAwKSkgJT4lIAogICAgICBnZ3Bsb3QoKSArIGdlb21fc2YoYWVzKGZpbGwgPSBkYXRhc2V0c19uKSkgKwogICAgICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0iYmx1ZSIsIGhpZ2g9InJlZCIpICsKICAgICAgdGhlbWVfYncoKSAKYGBgCgoKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CnAwICsgZ2d0aXRsZSgiQ292aWQgQ291bnQgRGF0YSBBdmFpbGFiaWxpdHkgYXQgdGhlIENvdW50cnkgTGV2ZWwiKQpgYGAKCmBgYHtyfQp0ZW1wIDwtIGdhZG0zNl9sZXZlbHNfMCAlPiUKICAgbGVmdF9qb2luKAogICBsaHNfbG9uZyAgJT4lIGNvdW50KGdpZCwgZGF0YXNldCkgJT4lIHJlbmFtZShHSURfMD1naWQpICN0aGVyZSBhcmUgc3RpbGwgZHVwZSBnZW9uYW1lcyB3aWtpZGF0YSB0byBnaWQgbWF0Y2hlcyB0aGF0IG5lZWQgdG8gYmUgZml4ZWQgZ2VvbmFtZWlkLCB3aWtpZGF0YV9pZCwgCikgCgp0ZW1wX3dpZGUgPC0gdGVtcCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBkcGx5cjo6c2VsZWN0KENvdW50cnk9TkFNRV8wLCBkYXRhc2V0LCBuKSAlPiUgZGlzdGluY3QoKSAlPiUgcGl2b3Rfd2lkZXIoIGlkX2NvbHMgPSBDb3VudHJ5LCBuYW1lc19mcm9tID0gZGF0YXNldCwKICB2YWx1ZXNfZnJvbSA9IG4sIHZhbHVlc19maWxsID0gTlVMTCwgdmFsdWVzX2ZuID0gTlVMTCkgCgp0ZW1wX3dpZGUgJT4lIERUOjpkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDIwLCBhdXRvV2lkdGggPSBUUlVFKSkKCiNpbnN0YWxsLnBhY2thZ2VzKCdndCcpCiNsaWJyYXJ5KGd0KQojdGVtcF93aWRlICU+JSBndCgpICU+JSAKIyB0YWJfaGVhZGVyKAojICAgIHRpdGxlID0gbWQoIkRhdGEgQXZhaWxhYmlsaXR5IGJ5IENvdW50cnkiKSwKIyAgICBzdWJ0aXRsZSA9ICJOdW1iZXIgb2YgRGF5cyB3aXRoIERhdGEgYnkgRGF0YXNldCIKIyAgKSAlPiUKIyAgZm10X21pc3NpbmcoIGNvbHVtbnM9ZXZlcnl0aGluZygpLCByb3dzPU5VTEwsbWlzc2luZ190ZXh0ID0gMCkKCmBgYAoKIyMgU3RhdGUvUHJvdmluY2UgTGV2ZWwgRGF0YSBBdmFpbGFiaWxpdHkKCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmdhZG0zNl9sZXZlbHNfMSA9IHN0X3JlYWQoIi9tZWRpYS9za3luZXQyLzkwNTg4NGYwLTc1NDYtNDI3My05MDYxLTEyYTc5MDgzMGJlYi9yd2RfZ2l0aHViX3ByaXZhdGUvTkVTU2NvdmlkMTkvZGF0YV90ZW1wL2dhZG0zNl9ieWNvdW50cnkvZ2FkbTM2X2xldmVsc19ncGtnL2dhZG0zNl9sZXZlbHMuZ3BrZyIsIGxheWVyPSJsZXZlbDEiKSAgJT4lCiAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IEZBTFNFLCBkVG9sZXJhbmNlID0wLjEpICMgIDAuMDI1IHRoaXMgaXMgc3VwcG9zZWRseSBicm9rZW4gdXAgYnkgNiBsZXZlbHMgYW5kIHNvIHNob3VsZCBoYXZlIHUucy4gCgoKcDEgPC0gZ2FkbTM2X2xldmVsc18xICU+JSAKICBsZWZ0X2pvaW4obGhzX2xvbmdfcGxhY2Vfc291cmNlcyAlPiUgZHBseXI6OnNlbGVjdChnaWQ9Z2lkLCBkYXRhc2V0c19uKSAlPiUgIGxlZnRfam9pbiggZ2FkbTM2X2xldmVsc18xICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIGRwbHlyOjpzZWxlY3QoZ2lkPUdJRF8xLCBOQU1FXzEpICU+JSBkaXN0aW5jdCgpICApCiAgKSAlPiUKICAjcmVwbGFjZV9uYShsaXN0KGRhdGFzZXRzX24gPSAwKSkgJT4lIAogIGdncGxvdCgpICsgZ2VvbV9zZihhZXMoZmlsbCA9IGRhdGFzZXRzX24pKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9ImJsdWUiLCBoaWdoPSJyZWQiKSArCiAgdGhlbWVfYncoKSAKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTYsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFfQpwMQpgYGAKCmBgYHtyfQp0ZW1wIDwtIGdhZG0zNl9sZXZlbHNfMSAlPiUKICAgbGVmdF9qb2luKAogICBsaHNfbG9uZyAgJT4lIGNvdW50KGdpZCwgZGF0YXNldCkgJT4lIHJlbmFtZShHSURfMT1naWQpICN0aGVyZSBhcmUgc3RpbGwgZHVwZSBnZW9uYW1lcyB3aWtpZGF0YSB0byBnaWQgbWF0Y2hlcyB0aGF0IG5lZWQgdG8gYmUgZml4ZWQgZ2VvbmFtZWlkLCB3aWtpZGF0YV9pZCwgCikgCgp0ZW1wX3dpZGUgPC0gdGVtcCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBkcGx5cjo6c2VsZWN0KENvdW50cnk9TkFNRV8wLCBBZG1pbjE9TkFNRV8xLCBkYXRhc2V0LCBuKSAlPiUgZGlzdGluY3QoKSAlPiUgcGl2b3Rfd2lkZXIoIGlkX2NvbHMgPSBDb3VudHJ5OkFkbWluMSwgbmFtZXNfZnJvbSA9IGRhdGFzZXQsCiAgdmFsdWVzX2Zyb20gPSBuLCB2YWx1ZXNfZmlsbCA9IE5VTEwsIHZhbHVlc19mbiA9IE5VTEwpICU+JSBtdXRhdGUodG90YWwgPSByb3dTdW1zKC5bLWMoMSwyKV0sIG5hLnJtID0gVCkpCgp0ZW1wX3dpZGUgJT4lIGZpbHRlcih0b3RhbD4wKSAlPiUgRFQ6OmRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsIGF1dG9XaWR0aCA9IFRSVUUpKQoKYGBgCgojIyBDb3VudHkgRGlzdHJpY3QgTGV2ZWwgRGF0YSBBdmFpbGFiaWxpdHkKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTIsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KZ2FkbTM2X2xldmVsc18yID0gc3RfcmVhZCgiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvZ2FkbTM2X2J5Y291bnRyeS9nYWRtMzZfbGV2ZWxzX2dwa2cvZ2FkbTM2X2xldmVscy5ncGtnIiwgbGF5ZXI9ImxldmVsMiIpICAlPiUKICBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gRkFMU0UsIGRUb2xlcmFuY2UgPSAwLjAwMSkgIyAgMC4wMjUgdGhpcyBpcyBzdXBwb3NlZGx5IGJyb2tlbiB1cCBieSA2IGxldmVscyBhbmQgc28gc2hvdWxkIGhhdmUgdS5zLiBJIGhhdmUgdG8ga2VlcCBzaHJpbmtpbmcgaXQgc28gbWlzaXNuZyBnb2VzIHRvIHplcm8gCgpwMiA8LSBnYWRtMzZfbGV2ZWxzXzIgJT4lIAogIGxlZnRfam9pbihsaHNfbG9uZ19wbGFjZV9zb3VyY2VzICU+JSBkcGx5cjo6c2VsZWN0KGdpZD1naWQsIGRhdGFzZXRzX24pICU+JSAgbGVmdF9qb2luKCBnYWRtMzZfbGV2ZWxzXzIgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgZHBseXI6OnNlbGVjdChnaWQ9R0lEXzIsIE5BTUVfMikgJT4lIGRpc3RpbmN0KCkgICkKICApICU+JQogICNyZXBsYWNlX25hKGxpc3QoZGF0YXNldHNfbiA9IDApKSAlPiUgCiAgZ2dwbG90KCkgKyBnZW9tX3NmKGFlcyhmaWxsID0gZGF0YXNldHNfbiksbHdkID0gMCkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93PSJibHVlIiwgaGlnaD0icmVkIikgKwogIHRoZW1lX2J3KCkgCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02LHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KcDIKYGBgCgoKYGBge3J9CnRlbXAgPC0gZ2FkbTM2X2xldmVsc18yICU+JQogICBsZWZ0X2pvaW4oCiAgIGxoc19sb25nICAlPiUgY291bnQoZ2lkLCBkYXRhc2V0KSAlPiUgcmVuYW1lKEdJRF8yPWdpZCkgI3RoZXJlIGFyZSBzdGlsbCBkdXBlIGdlb25hbWVzIHdpa2lkYXRhIHRvIGdpZCBtYXRjaGVzIHRoYXQgbmVlZCB0byBiZSBmaXhlZCBnZW9uYW1laWQsIHdpa2lkYXRhX2lkLCAKKSAKCnRlbXBfd2lkZSA8LSB0ZW1wICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIGRwbHlyOjpzZWxlY3QoQ291bnRyeT1OQU1FXzAsIEFkbWluMT1OQU1FXzEsIEFkbWluMj1OQU1FXzIsIGRhdGFzZXQsIG4pICU+JSBkaXN0aW5jdCgpICU+JSBwaXZvdF93aWRlciggaWRfY29scyA9IENvdW50cnk6QWRtaW4yLCBuYW1lc19mcm9tID0gZGF0YXNldCwKICB2YWx1ZXNfZnJvbSA9IG4sIHZhbHVlc19maWxsID0gTlVMTCwgdmFsdWVzX2ZuID0gTlVMTCkgJT4lIG11dGF0ZSh0b3RhbCA9IHJvd1N1bXMoLlstYygxLDIsMyldLCBuYS5ybSA9IFQpKQoKdGVtcF93aWRlICU+JSBmaWx0ZXIodG90YWw+MCkgJT4lIERUOjpkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLCBhdXRvV2lkdGggPSBUUlVFKSkKCmBgYAoKIyBEYXRhIEF2YWlsYWJpbGl0eSBhbmQgSW50ZXJwb2xhdGlvbiBvdmVyIFRpbWUKCmBgYHtyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CgojdGVzdCA8LSBsaHNfbG9uZyAlPiUgZ3JvdXBfYnkoZGF0YXNldCwgZ2lkLCBnZW9uYW1laWQsIHdpa2lkYXRhX2lkLCBkYXRlX2FzZGF0ZSkgJT4lIHN1bW1hcml6ZShuPW4oKSkKCmFsbF9uYSA8LSBmdW5jdGlvbih4KSBhbnkoIWlzLm5hKHgpKSAjaHR0cHM6Ly9pbnRlbGxpcGFhdC5jb20vY29tbXVuaXR5LzEyOTk5L3JlbW92ZS1jb2x1bW5zLWZyb20tZGF0YWZyYW1lLXdoZXJlLWFsbC12YWx1ZXMtYXJlLW5hCgojYmluZyBsb29rcyBvZmYgYnkgYSBkYXkgZnJvbSB0aGUgb3RoZXIgb25lcwpsaHNfd2lkZV9xY29kZSA8LSBsaHNfbG9uZyAlPiUgCiAgICAgICAgICAgICAgICAgIGZpbHRlcighaXMubmEod2lraWRhdGFfaWQpICYgIWlzLm5hKGRhdGVfYXNkYXRlKSkgJT4lCiAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KGdpZCwgZ2VvbmFtZWlkLCB3aWtpZGF0YV9pZCwgZGF0ZV9hc2RhdGUpICU+JSAgbXV0YXRlKGNvbmZpcm1lZF92YXI9dmFyKGNvbmZpcm1lZCwgbmEucm09VCksIGRlYXRoc192YXI9dmFyKGRlYXRocywgbmEucm09VCkpICU+JSB1bmdyb3VwKCkgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoZGF0YXNldCwgZ2lkLCBnZW9uYW1laWQsIHdpa2lkYXRhX2lkLCBkYXRlX2FzZGF0ZSxjb25maXJtZWQsIGRlYXRocywgdGVzdGVkX3NhbXBsZXMsIHRlc3RlZF9wZW9wbGUpICU+JQogICAgICAgICAgICAgICAgICBncm91cF9ieShkYXRhc2V0LCBnaWQsIGdlb25hbWVpZCwgd2lraWRhdGFfaWQsIGRhdGVfYXNkYXRlKSAlPiUgIHN1bW1hcmlzZV9pZihpcy5udW1lcmljLG1heCxuYS5ybT1UKSAlPiUgdW5ncm91cCgpICU+JSAjdGhpcyBpcyBhIGhhY2ssIHdlIHNob3VsZCBoYXZlIGR1cGVzIHdpdGhpbiBkYXRhc2V0cwogICAgICAgICAgICAgICAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZGF0YXNldCwgdmFsdWVzX2Zyb20gPSBjKGNvbmZpcm1lZCwgZGVhdGhzLCB0ZXN0ZWRfc2FtcGxlcywgdGVzdGVkX3Blb3BsZSkgKSAlPiUgCiAgICAgICAgICAgICAgICAgIG11dGF0ZV9pZihpcy5udW1lcmljLCBsaXN0KH5uYV9pZihhYnMoLiksIEluZikpKSAlPiUgI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzEyMTg4NTA5L2NsZWFuaW5nLWluZi12YWx1ZXMtZnJvbS1hbi1yLWRhdGFmcmFtZQogICAgICAgICAgICAgICAgICBzZWxlY3RfaWYoYWxsX25hKSAKCmRpbShsaHNfd2lkZV9xY29kZSkgIzgyLDE1NyA4MmsgcGxhY2UvZGF5IG9ic2VydmF0aW9ucwoKbGVuZ3RoKHVuaXF1ZShsaHNfd2lkZV9xY29kZSR3aWtpZGF0YV9pZCkpICMzNjk3ICNhbG1vc3QgNGsgCgp0ZXN0IDwtIGxoc193aWRlX3Fjb2RlICU+JSBkcGx5cjo6c2VsZWN0KHN0YXJ0c193aXRoKCJjb25maXJtZWQiKSkgJT4lIGRpc3RpbmN0KCkgCiNjb3IodGVzdCwgdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQoKbGhzX2xvbmdfbWVkaWFuIDwtIGxoc19sb25nICU+JSBncm91cF9ieShnaWQsIGdlb25hbWVpZCwgd2lraWRhdGFfaWQsIGRhdGVfYXNkYXRlKSAlPiUgc3VtbWFyaXplX2lmKGlzLm51bWVyaWMsIG1lZGlhbiwgbmEucm09VCkgJT4lIGRwbHlyOjpzZWxlY3QoLWVuZHNfd2l0aCgiX2ZkIikpICU+JSAjd2UgdGFrZSB0aGUgbWVkaWFuIGFjcm9zcyBvYnNlcnZhdGlvbnMKICAgICAgICAgICAgICAgICAgIG11dGF0ZShDRlI9ZGVhdGhzL2NvbmZpcm1lZCkKI2RpbShsaHNfbG9uZ19tZWRpYW4pCiNzdW1tYXJ5KGxoc19sb25nX21lZGlhbikKYGBgCgpIZXJlIHdlIGRvIHRoZSBhY3R1YWwgaW50ZXJwb2xhdGlvbi4gRm9yIGVhY2ggaW5kaXZpZHVhbCBsb2NhdGlvbi1kYXRhc2V0LCB3ZSBmaXQgYSBwaWVjZXdpc2UgbGluZWFyIG1vZGVsIG92ZXIgdGltZSwgYW5kIHRoZW4gdXNlIHRoYXQgdG8gYXZlcmFnZSBvdmVyIGRheSB0byBkYXkgbm9pc2UgYW5kIGludGVycG9sYXRlIGJldHdlZW4gb2JzZXJ2YXRpb25zLiBCZWNhdXNlIHRoaXMgaXMgaW4gbG9nIHNwYWNlLCB0aGUgc2xvcGUgb2YgdGhhdCBsaW5lIGlzIHRoZSBkYXkgb24gZGF5IHBlcmNlbnQgaW5jcmVhc2UgaW4gdGhlIGNvdW50LiBXZSBmaW5pc2ggYnkgZml0dGluZyBhIHBpZWNld2lzZSBpbnRlcmNlcHQgbW9kZWwgdG8gdGhvc2Ugc2xvcGVzIHRvIGdldCBhIHNpbmdsZSBkYWlseSBlc3RpbWF0ZSBvZiBob3cgbXVjaCB0aGUgY291bnQgaXMgaW5jcmVhc2luZy4gRGF0YXNldHMgYXJlIGFibGUgdG8gZGlzYWdyZWUgaW4gbG90cyBvZiBkaWZmZXJlbnQgd2F5cyBhbmQgd2Ugc3RpbGwgcmVjb3ZlciBhIGNvcnJlY3QgcmF0ZSBvZiBjaGFuZ2UuCgojIyBJbnRlcnBvbGF0aW9uIG9mIENvdW50cwoKVG8gZWFjaCBpbmRpdmlkdWFsIGRhdGFzZXQtbG9jYXRpb24gc2VyaWVzLCB3ZSBmaXQgYSBwaWVjZXdpc2UgbGluZWFyIHRyZW5kLiBFYWNoIHNlZ21lbnQgaXMgcmVxdWlyZWQgdG8gaGF2ZSBhdCBsZWFzdCAzIG9ic2VydmF0aW9ucywgYnV0IG90aGVyd2lzZSB3ZSBtYWtlIG5vIG90aGVyIGNvbnN0cmFpbnRzLiBUaGlzIGFsbG93cyB1cyB0byBmbGV4aWJseSBmaXQgbGluZWFyIHNlZ21lbnRzIGFzIHdlbGwgYXMgdGlnaHQgY3VydmVzLiBXZSBhbHNvIGFsbG93IGZvciBzdHJ1Y3R1cmFsIGJyZWFrcyB3aGVyZSB0aGUgc2VyaWVzIHN0b3BzLCBoYXMgYSBzdHJ1Y3R1cmFsIHNoaWZ0IHVwIG9yIGRvd24gYmVjYXVzZSBzYXkgYSBjaGFuZ2UgaW4gcmVwb3J0aW5nIHJ1bGVzLCBidXQgb3RoZXIgdGhlbiBvdGhlcndpc2UgY29udGludWVzIGFzIG5vcm1hbC4gV2UgdGFrZSB0aGUgbGluZWFyIHRyZW5kIGZpdCBhcyBvdXIgYmVzdCBlc3RpbWF0ZSBhdCBlYWNoIHBvaW50LiBUaGlzIGF2ZXJhZ2VzIG92ZXIgZGF5IHRvIGRheSBub2lzZSwgZS5nLiB1bmRlciByZXBvcnRpbmcgb24gdGhlIHdlZWtlbmQuIEl0IGFsc28gYWxsb3dzIHVzIHRvIGludGVycG9sYXRlIGJldHdlZW4gb2JzZXJ2YXRpb25zIHdoZXJlIHRoZXJlIGlzIG1pc3NpbmduZXNzIGluIHRoZSBzZXJpZXMgYnV0IHdlIGhhdmUgcmVhc29uYWJsZSBiZWxpZWZzIHRoZSB0cnVlIG1lYXN1cmUgY29udGludWVkIGxpbmVhcmx5IGJldHdlZW4gdGhlIG9ic2VydmVkIHBvaW50cy4KCmBgYHtyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KCmRhdGFzZXRfcGxhY2VzIDwtIGxoc19sb25nX2NsZWFuICU+JSBkcGx5cjo6c2VsZWN0KGRhdGFzZXRfZ2lkX2dlb25hbWVpZF93aWtpZGF0YV9pZCkgJT4lIGRpc3RpbmN0KCkgJT4lIHB1bGwoZGF0YXNldF9naWRfZ2VvbmFtZWlkX3dpa2lkYXRhX2lkKQpsaWJyYXJ5KHBhcnR5KQp0ZW1wX2xpc3QxIDwtIGxpc3QoKQpmb3IocSBpbiBkYXRhc2V0X3BsYWNlcyAgKXsKICAgICAgdHJ5KHsKICAgICAgICB0ZW1wIDwtIE5VTEwKICAgICAgICB0ZW1wIDwtIGxoc19sb25nX2NsZWFuICU+JQogICAgICAgICAgICAgICAgZmlsdGVyKGRhdGFzZXRfZ2lkX2dlb25hbWVpZF93aWtpZGF0YV9pZCAlaW4lIHEpICU+JQogICAgICAgICAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgJT4lCgogICAgICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9sb2c9bG9nKGNvbmZpcm1lZCkpICU+JQogICAgICAgICAgICAgICAgbXV0YXRlKGRlYXRoc19sb2c9bG9nKGRlYXRocykpICU+JQogICAgICAgICAgICAgICAgbXV0YXRlKHRlc3RlZF9wZW9wbGVfbG9nPWxvZyh0ZXN0ZWRfcGVvcGxlKSkgJT4lCiAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3NhbXBsZXNfbG9nPWxvZyh0ZXN0ZWRfc2FtcGxlcykpIAogICAgICAgICAgCiAgICAgICAgaWYobnJvdyh0ZW1wKT09MCl7bmV4dCgpfQogICAgICAgIAogICAgICAgIHRlbXAgPC0gdGVtcCAlPiUgZXhwYW5kKGRhdGFzZXQsIGdpZF9nZW9uYW1laWRfd2lraWRhdGFfaWQsIGdpZCwgZ2VvbmFtZWlkLHdpa2lkYXRhX2lkLCBkYXRlX2FzZGF0ZT1taW4oZGF0ZV9hc2RhdGUpOm1heChkYXRlX2FzZGF0ZSkgJT4lIGFzX2RhdGUoKSApICU+JSAKICAgICAgICAgICAgICAgICBmdWxsX2pvaW4odGVtcCkgJT4lIAogICAgICAgICAgICAgICAgIG11dGF0ZShkYXRlX2FzbnVtZXJpYz0gYXMubnVtZXJpYyhkYXRlX2FzZGF0ZSkgKSAlPiUgCiAgICAgICAgICAgICAgICAgYXJyYW5nZShkYXRlX2FzbnVtZXJpYykgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9ub25taXNzaW5nX2NvdW50ICAgICA9ICghaXMubmEoY29uZmlybWVkKSkgJT4lIGN1bXN1bSgpICkgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKGRlYXRoc19ub25taXNzaW5nX2NvdW50ICAgICA9ICghaXMubmEoZGVhdGhzKSkgJT4lIGN1bXN1bSgpICkgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKHRlc3RlZF9wZW9wbGVfbm9ubWlzc2luZ19jb3VudCAgICAgPSAoIWlzLm5hKHRlc3RlZF9wZW9wbGUpKSAlPiUgY3Vtc3VtKCkgKSAlPiUKICAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3NhbXBsZXNfbm9ubWlzc2luZ19jb3VudCAgICAgPSAoIWlzLm5hKHRlc3RlZF9zYW1wbGVzKSkgJT4lIGN1bXN1bSgpICkgJT4lCiAgICAgICAgCiAgICAgICAgICAgICAgICAgYXJyYW5nZSgtZGF0ZV9hc251bWVyaWMpICU+JQogICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbm9ubWlzc2luZ19jb3VudF9yZXZlcnNlZCAgICAgPSAoIWlzLm5hKGNvbmZpcm1lZCkpICU+JSBjdW1zdW0oKSApICU+JQogICAgICAgICAgICAgICAgIG11dGF0ZShkZWF0aHNfbm9ubWlzc2luZ19jb3VudF9yZXZlcnNlZCAgICAgPSAoIWlzLm5hKGRlYXRocykpICU+JSBjdW1zdW0oKSApICU+JQogICAgICAgICAgICAgICAgIG11dGF0ZSh0ZXN0ZWRfcGVvcGxlX25vbm1pc3NpbmdfY291bnRfcmV2ZXJzZWQgICAgID0gKCFpcy5uYSh0ZXN0ZWRfcGVvcGxlKSkgJT4lIGN1bXN1bSgpICkgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKHRlc3RlZF9zYW1wbGVzX25vbm1pc3NpbmdfY291bnRfcmV2ZXJzZWQgICAgID0gKCFpcy5uYSh0ZXN0ZWRfc2FtcGxlcykpICU+JSBjdW1zdW0oKSApICU+JSAKICAgICAgICAgICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAKCiAgICAgICAgdHJ5Q2F0Y2goeyAgCiAgICAgICAgICBpZihzdW0oIWlzLm5hKHRlbXAkY29uZmlybWVkX2xvZykpPj0zKXsgI25lZWQgYXQgbGVhc3QgMyBwb2ludHMKICAgICAgICAgICAgdHJlZV9jb25maXJtZWQgPC0gcGFydHk6Om1vYihjb25maXJtZWRfbG9nIH4gMSArIGRhdGVfYXNudW1lcmljICAgIHwgZGF0ZV9hc251bWVyaWMgLCBjb250cm9sID0gbW9iX2NvbnRyb2wobWluc3BsaXQgPSAzLCBhbHBoYT0uMiksIGRhdGEgPSB0ZW1wLCAgbW9kZWwgPSBsaW5lYXJNb2RlbCkgICMgKyBJKGRhdGVfYXNudW1lcmljXjIpICAKICAgICAgICAgICAgdGVtcCRjb25maXJtZWRfbG9nX3lfaGF0IDwtIHByZWRpY3QoIHRyZWVfY29uZmlybWVkLCBuZXdkYXRhPXRlbXAgLCB0eXBlID0gYygicmVzcG9uc2UiKSApCiAgICAgICAgICAgIHRlbXAkY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIgPC0gIHByZWRpY3QoIHRyZWVfY29uZmlybWVkLCBuZXdkYXRhPXRlbXAgLCB0eXBlID0gYygibm9kZSIpKQogICAgICAgICAgICB0ZW1wIDwtIHRlbXAgJT4lIAogICAgICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nX3lfaGF0ICAgICAgID1pZmVsc2UoY29uZmlybWVkX25vbm1pc3NpbmdfY291bnQ+MCAmIGNvbmZpcm1lZF9ub25taXNzaW5nX2NvdW50X3JldmVyc2VkPjAsY29uZmlybWVkX2xvZ195X2hhdCxOQSkpICU+JSAjb25seSBpbnRlcnBvbGF0ZSB3aXRoaW4gdGhlIG9ic2VydmVkIGRhdGEsIG5ldmVyIGJlZm9yZSBvciBhZnRlcgogICAgICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcj1pZmVsc2UoY29uZmlybWVkX25vbm1pc3NpbmdfY291bnQ+MCAmIGNvbmZpcm1lZF9ub25taXNzaW5nX2NvdW50X3JldmVyc2VkPjAsY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIsTkEpKSAlPiUgI29ubHkgaW50ZXJwb2xhdGUgd2l0aGluIHRoZSBvYnNlcnZlZCBkYXRhLCBuZXZlciBiZWZvcmUgb3IgYWZ0ZXIKCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIpICU+JQogICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc251bWVyaWMpICU+JQogICAgICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nX3lfaGF0X3Nsb3BlPXRzaWJibGU6OmRpZmZlcmVuY2UoY29uZmlybWVkX2xvZ195X2hhdCkpICU+JSAKICAgICAgICAgICAgICAgICAgICBmaWxsKGNvbmZpcm1lZF9sb2dfeV9oYXRfc2xvcGUsIC5kaXJlY3Rpb249InVwIikgJT4lIAogICAgICAgICAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUKICAgICAgICAgICAgICAgICAgICBtdXRhdGUoY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IHJvdW5kKChleHAoY29uZmlybWVkX2xvZ195X2hhdF9zbG9wZSktMSkqMTAwLDIpKSAgJT4lCiAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9sb2dfeV9oYXQ9aWZlbHNlKGNvbmZpcm1lZF9sb2dfeV9oYXQ8MCxOQSwgY29uZmlybWVkX2xvZ195X2hhdCkpCiAgICAgICAgICB9CiAgICAgICAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7fSkKICAgICAgICAKICAgICAgICB0cnlDYXRjaCh7ICAKICAgICAgICAgIGlmKHN1bSghaXMubmEodGVtcCRkZWF0aHNfbG9nKSk+PTMpeyAjbmVlZCBhdCBsZWFzdCAzIHBvaW50cwogICAgICAgICAgICB0cmVlX2RlYXRocyA8LSBwYXJ0eTo6bW9iKGRlYXRoc19sb2cgfiAxICsgZGF0ZV9hc251bWVyaWMgICAgfCBkYXRlX2FzbnVtZXJpYyAsIGNvbnRyb2wgPSBtb2JfY29udHJvbChtaW5zcGxpdCA9IDMsIGFscGhhPS4yKSwgZGF0YSA9IHRlbXAsICBtb2RlbCA9IGxpbmVhck1vZGVsKSAgIyArIEkoZGF0ZV9hc251bWVyaWNeMikgICAgCiAgICAgICAgICAgIHRlbXAkZGVhdGhzX2xvZ195X2hhdCA8LSBwcmVkaWN0KCB0cmVlX2RlYXRocywgbmV3ZGF0YT10ZW1wICwgdHlwZSA9IGMoInJlc3BvbnNlIikgKQogICAgICAgICAgICB0ZW1wJGRlYXRoc19sb2dfZ3JvdXBfbnVtYmVyIDwtICBwcmVkaWN0KCB0cmVlX2RlYXRocywgbmV3ZGF0YT10ZW1wICwgdHlwZSA9IGMoIm5vZGUiKSkKICAgICAgICAgICAgdGVtcCA8LSB0ZW1wICU+JSAKICAgICAgICAgICAgICAgICAgICBtdXRhdGUoZGVhdGhzX2xvZ195X2hhdD1pZmVsc2UoZGVhdGhzX25vbm1pc3NpbmdfY291bnQ+MCAmIGRlYXRoc19ub25taXNzaW5nX2NvdW50X3JldmVyc2VkPjAsZGVhdGhzX2xvZ195X2hhdCxOQSkpICU+JSAjb25seSBpbnRlcnBvbGF0ZSB3aXRoaW4gdGhlIG9ic2VydmVkIGRhdGEsIG5ldmVyIGJlZm9yZQogICAgICAgICAgICAgICAgICAgIG11dGF0ZShkZWF0aHNfbG9nX2dyb3VwX251bWJlcj1pZmVsc2UoZGVhdGhzX25vbm1pc3NpbmdfY291bnQ+MCAmIGRlYXRoc19ub25taXNzaW5nX2NvdW50X3JldmVyc2VkPjAsZGVhdGhzX2xvZ19ncm91cF9udW1iZXIsTkEpKSAlPiUgI29ubHkgaW50ZXJwb2xhdGUgd2l0aGluIHRoZSBvYnNlcnZlZCBkYXRhLCBuZXZlciBiZWZvcmUKCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoZGVhdGhzX2xvZ19ncm91cF9udW1iZXIpICU+JSAKICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKGRhdGVfYXNudW1lcmljKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGRlYXRoc19sb2dfeV9oYXRfc2xvcGU9dHNpYmJsZTo6ZGlmZmVyZW5jZShkZWF0aHNfbG9nX3lfaGF0KSkgJT4lCiAgICAgICAgICAgICAgICAgICAgZmlsbChkZWF0aHNfbG9nX3lfaGF0X3Nsb3BlLCAuZGlyZWN0aW9uPSJ1cCIpICU+JQogICAgICAgICAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUKICAgICAgICAgICAgICAgICAgICBtdXRhdGUoZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IHJvdW5kKChleHAoZGVhdGhzX2xvZ195X2hhdF9zbG9wZSktMSkqMTAwLDIpKSAlPiUKICAgICAgICAgICAgICAgICAgICBtdXRhdGUoZGVhdGhzX2xvZ195X2hhdD1pZmVsc2UoZGVhdGhzX2xvZ195X2hhdDwwLE5BLCBkZWF0aHNfbG9nX3lfaGF0KSkgI3JlamVjdCBhbnkgd2hlcmUgdGhlIHByZWRpY3Rpb24gaXMgbGVzcyB0aGFuIDEgZnVsbCBjYXNlCiAgICAgICAgICB9CiAgICAgICAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7fSkKICAgICAgICAKICAgICAgICB0cnlDYXRjaCh7ICAKICAgICAgICAgIGlmKHN1bSghaXMubmEodGVtcCR0ZXN0ZWRfcGVvcGxlX2xvZykpPj0zKXsgI25lZWQgYXQgbGVhc3QgMyBwb2ludHMKICAgICAgICAgICAgdHJlZV90ZXN0ZWRfcGVvcGxlIDwtIHBhcnR5Ojptb2IodGVzdGVkX3Blb3BsZV9sb2cgfiAxICsgZGF0ZV9hc251bWVyaWMgICAgfCBkYXRlX2FzbnVtZXJpYyAsIGNvbnRyb2wgPSBtb2JfY29udHJvbChtaW5zcGxpdCA9IDMsIGFscGhhPS4yKSwgZGF0YSA9IHRlbXAsICBtb2RlbCA9IGxpbmVhck1vZGVsKSAgIyArIEkoZGF0ZV9hc251bWVyaWNeMikgICAKICAgICAgICAgICAgdGVtcCR0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdCA8LSBwcmVkaWN0KCB0cmVlX3Rlc3RlZF9wZW9wbGUsIG5ld2RhdGE9dGVtcCAsIHR5cGUgPSBjKCJyZXNwb25zZSIpICkKICAgICAgICAgICAgdGVtcCR0ZXN0ZWRfcGVvcGxlX2xvZ19ncm91cF9udW1iZXIgPC0gIHByZWRpY3QoIHRyZWVfdGVzdGVkX3Blb3BsZSwgbmV3ZGF0YT10ZW1wICwgdHlwZSA9IGMoIm5vZGUiKSkKICAgICAgICAgICAgdGVtcCA8LSB0ZW1wICU+JSAKICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQ9aWZlbHNlKHRlc3RlZF9wZW9wbGVfbm9ubWlzc2luZ19jb3VudD4wICYgdGVzdGVkX3Blb3BsZV9ub25taXNzaW5nX2NvdW50X3JldmVyc2VkPjAsdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsTkEpKSAlPiUgI29ubHkgaW50ZXJwb2xhdGUgd2l0aGluIHRoZSBvYnNlcnZlZCBkYXRhLCBuZXZlciBiZWZvcmUKICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3Blb3BsZV9sb2dfZ3JvdXBfbnVtYmVyPWlmZWxzZSh0ZXN0ZWRfcGVvcGxlX25vbm1pc3NpbmdfY291bnQ+MCAmIHRlc3RlZF9wZW9wbGVfbm9ubWlzc2luZ19jb3VudF9yZXZlcnNlZD4wLHRlc3RlZF9wZW9wbGVfbG9nX2dyb3VwX251bWJlcixOQSkpICU+JSAjb25seSBpbnRlcnBvbGF0ZSB3aXRoaW4gdGhlIG9ic2VydmVkIGRhdGEsIG5ldmVyIGJlZm9yZQogICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KHRlc3RlZF9wZW9wbGVfbG9nX2dyb3VwX251bWJlcikgJT4lIAogICAgICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc251bWVyaWMpICU+JQogICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9zbG9wZT10c2liYmxlOjpkaWZmZXJlbmNlKHRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0KSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgIGZpbGwodGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfc2xvcGUsIC5kaXJlY3Rpb249InVwIikgJT4lIHVuZ3JvdXAoKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSByb3VuZCgoZXhwKHRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3Nsb3BlKS0xKSoxMDAsMikpICU+JQogICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdD1pZmVsc2UodGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQ8MCxOQSwgdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQpKSAjcmVqZWN0IGFueSB3aGVyZSB0aGUgcHJlZGljdGlvbiBpcyBsZXNzIHRoYW4gMSBmdWxsIGNhc2UKICAgICAgICAgIH0KICAgICAgICB9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIHt9KQogICAgICAgIAogICAgICAgIHRlbXBfbGlzdDFbW3EgXV0gPC0gdGVtcAogIAogICAgICB9KQp9Cmxoc19sb25nX2NsZWFuX2ltcHV0ZWQxIDwtIGJpbmRfcm93cyh0ZW1wX2xpc3QxKQpkaW0obGhzX2xvbmdfY2xlYW5faW1wdXRlZDEpICM1MDAsNzg2ICNiaWdnZXIgYmVjYXVzZSB3ZSdyZSBpbnRlcnBvbGF0aW5nIG5vdwoKI3J0MSA8LSBycGFydChmb3JtdWxhID0gY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IGRhdGVfYXNudW1lcmljLCBkYXRhPXRlc3QpCiNpbnRlcnBvbGF0ZWQgPSBkYXRhLmZyYW1lKGRhdGVfYXNudW1lcmljPW1pbih0ZXN0JGRhdGVfYXNudW1lcmljKTptYXgodGVzdCRkYXRlX2FzbnVtZXJpYykgKQojaW50ZXJwb2xhdGVkJGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgPC0gIHByZWRpY3QocnQxLCBuZXdkYXRhPWludGVycG9sYXRlZCkKI2ludGVycG9sYXRlZCRkYXRlX2FzZGF0ZSA8LSBhcy5EYXRlKGludGVycG9sYXRlZCRkYXRlX2FzbnVtZXJpYykKCnBsYWNlcyA8LSBsaHNfbG9uZ19jbGVhbiAlPiUgZHBseXI6OnNlbGVjdChnaWRfZ2VvbmFtZWlkX3dpa2lkYXRhX2lkKSAlPiUgZGlzdGluY3QoKSAlPiUgcHVsbChnaWRfZ2VvbmFtZWlkX3dpa2lkYXRhX2lkKQoKbGlicmFyeShycGFydCkKbWluc3BsaXQ9NgptaW5idWNrZXQ9Mwp0ZW1wX2xpc3QyIDwtIGxpc3QoKQpmb3IocSBpbiBwbGFjZXMgKXsKICBwcmludChxKQogIHRlbXAgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZDEgJT4lIAogICAgICAgICAgICAgICAgIGZpbHRlcihnaWRfZ2VvbmFtZWlkX3dpa2lkYXRhX2lkICVpbiUgcSkgJT4lIAogICAgICAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc251bWVyaWMpIAogICAgCiAgICAgICAgICAKICB0cnlDYXRjaCh7ICAKICAgIHJ0MSA8LSBycGFydDo6cnBhcnQoZm9ybXVsYSA9IGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiBkYXRlX2FzbnVtZXJpYywKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT10ZW1wICU+JSBmaWx0ZXIoIWlzLm5hKGNvbmZpcm1lZF9sb2cpKSwgI3RvIGtlZXAgZnJvbSBmaXR0aW5nIHRvIGludGVycG9sYXRlIHNsb3BlcyB0aGF0IGFyZSBvdXQgb2YgZG9tYWluIGFuZCB1c3VhbGx5IHdyb25nLCByZXF1aXJlIGNvbmZpcm1lZCB0byBub3QgYmUgbWlzc2luZyBvciBuYQogICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gcnBhcnQuY29udHJvbChtaW5zcGxpdCA9IG1pbnNwbGl0LCBtaW5idWNrZXQ9bWluYnVja2V0KSkKICAgIHRlbXAkY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCA8LSAgcHJlZGljdChydDEsIG5ld2RhdGE9dGVtcCkgI3RoaXMgcHJlZGljdGlvbiBoZWxwZnVsbHkgdHJpZXMgdG8gaW1wdXRlIGJhY2t3YXJkcyBldmVuIGJlZm9yZSB0aGVyZSBhcmUgYW55IGRheSBpbiBhbnkgc2VyaWVzCiAgICAjV2UgbmVlZCB0byBudWtlIGl0IGlmIG5vIGRhdGEgZXhpc3QKICAgIHRlbXAgPC0gdGVtcCAlPiUKICAgICAgICAgICAgZ3JvdXBfYnkoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgICBtdXRhdGUoIGNvbmZpcm1lZF9ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzPXN1bShjb25maXJtZWRfbm9ubWlzc2luZ19jb3VudD4wLG5hLnJtPVQpICkgJT4lCiAgICAgICAgICAgIG11dGF0ZSggY29uZmlybWVkX25vbm1pc3NpbmdfY291bnRfZGF0YXNldHNfcmV2ZXJzZWQ9c3VtKGNvbmZpcm1lZF9ub25taXNzaW5nX2NvdW50X3JldmVyc2VkPjAsbmEucm09VCkgKSAlPiUKICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQ9aWZlbHNlKGNvbmZpcm1lZF9ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzPjAgJiBjb25maXJtZWRfbm9ubWlzc2luZ19jb3VudF9kYXRhc2V0c19yZXZlcnNlZD4wLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQsTkEpKSAgJT4lCiAgICAgIHVuZ3JvdXAoKQogICAgCiAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7fSkKICAKICB0cnlDYXRjaCh7ICAKICAgIHJ0MiA8LSBycGFydDo6cnBhcnQoZm9ybXVsYSA9IGRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiBkYXRlX2FzbnVtZXJpYywKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT10ZW1wICU+JSBmaWx0ZXIoIWlzLm5hKGRlYXRoc19sb2cpKSwKICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IHJwYXJ0LmNvbnRyb2wobWluc3BsaXQgPSBtaW5zcGxpdCwgbWluYnVja2V0PW1pbmJ1Y2tldCkpCiAgICB0ZW1wJGRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgPC0gIHByZWRpY3QocnQyLCBuZXdkYXRhPXRlbXApCiAgICB0ZW1wIDwtIHRlbXAgJT4lCiAgICAgICAgZ3JvdXBfYnkoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgIG11dGF0ZSggZGVhdGhzX25vbm1pc3NpbmdfY291bnRfZGF0YXNldHM9c3VtKGRlYXRoc19ub25taXNzaW5nX2NvdW50PjAsbmEucm09VCkgKSAlPiUKICAgICAgICBtdXRhdGUoIGRlYXRoc19ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzX3JldmVyc2VkPXN1bShkZWF0aHNfbm9ubWlzc2luZ19jb3VudF9yZXZlcnNlZD4wLG5hLnJtPVQpICkgJT4lCiAgICAgICAgbXV0YXRlKGRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQ9aWZlbHNlKGRlYXRoc19ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzPjAgJiBkZWF0aHNfbm9ubWlzc2luZ19jb3VudF9kYXRhc2V0c19yZXZlcnNlZD4wLGRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQsTkEpKSAlPiUKICAgICAgdW5ncm91cCgpCiAgICAgICAgCiAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7fSkKCiAgdHJ5Q2F0Y2goeyAgCiAgICBydDMgPC0gcnBhcnQ6OnJwYXJ0KGZvcm11bGEgPSB0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IGRhdGVfYXNudW1lcmljLAogICAgICAgICAgICAgICAgICAgIGRhdGE9dGVtcCAlPiUgZmlsdGVyKCFpcy5uYSh0ZXN0ZWRfcGVvcGxlX2xvZykpLAogICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBycGFydC5jb250cm9sKG1pbnNwbGl0ID0gbWluc3BsaXQsIG1pbmJ1Y2tldD1taW5idWNrZXQpKQogICAgdGVtcCR0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCA8LSAgcHJlZGljdChydDMsIG5ld2RhdGE9dGVtcCwgY29udHJvbCA9IHJwYXJ0LmNvbnRyb2wobWluc3BsaXQgPSBtaW5zcGxpdCwgbWluYnVja2V0PW1pbmJ1Y2tldCkpCiAgICB0ZW1wIDwtIHRlbXAgJT4lCiAgICAgICAgZ3JvdXBfYnkoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgIG11dGF0ZSggdGVzdGVkX3Blb3BsZV9ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzPXN1bSh0ZXN0ZWRfcGVvcGxlX25vbm1pc3NpbmdfY291bnQ+MCxuYS5ybT1UKSApICU+JQogICAgICAgIG11dGF0ZSggdGVzdGVkX3Blb3BsZV9ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzX3JldmVyc2VkPXN1bSh0ZXN0ZWRfcGVvcGxlX25vbm1pc3NpbmdfY291bnRfcmV2ZXJzZWQ+MCxuYS5ybT1UKSApICU+JQogICAgICAKICAgICAgICBtdXRhdGUodGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQ9aWZlbHNlKHRlc3RlZF9wZW9wbGVfbm9ubWlzc2luZ19jb3VudF9kYXRhc2V0cz4wICYgdGVzdGVkX3Blb3BsZV9ub25taXNzaW5nX2NvdW50X2RhdGFzZXRzX3JldmVyc2VkPjAsdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQsTkEpKSAgJT4lCiAgICAgIHVuZ3JvdXAoKQogIH0sIGVycm9yID0gZnVuY3Rpb24oZSkge30pCiAgCiAgdGVtcF9saXN0MltbcSBdXSA8LSB0ZW1wCn0KbGhzX2xvbmdfY2xlYW5faW1wdXRlZDIgPC0gYmluZF9yb3dzKHRlbXBfbGlzdDIpCgpsaHNfbG9uZ19jbGVhbl9pbXB1dGVkIDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQyCmRpbShsaHNfbG9uZ19jbGVhbl9pbXB1dGVkKSAjNDE5OTEwICM0MTM0NzUgIzQwOCwzNjkgI3dlIGxvc2UgYW55d2l0aG91dCBxIGNvZGVzIGhlcmUKc2F2ZVJEUyhsaHNfbG9uZ19jbGVhbl9pbXB1dGVkLCAiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvbGhzX2xvbmdfY2xlYW5faW1wdXRlZC5SZHMiKQoKYGBgCgojIyMgRXhhbXBsZXMKCiMjIyMgQ2hpbmEKCmBgYHtyLCBmaWcud2lkdGg9MTYsIGZpZy5oZWlnaHQ9MTIsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KI0NoaW5hCiMiUTE0OCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMTQ4IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgpwX2ludGVycG9sYXRpb24wIDwtIHRlc3QgJT4lCiAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgICAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIkNoaW5hIFExNDggQ29uZmlybWVkIikgKyBmYWNldF93cmFwKH5kYXRhc2V0ICAgKQoKYGBgCgpEYXRhIG9uIENoaW5hIHNob3dzIHZhcmlhdGlvbiBhY3Jvc3MgZGF0YXNldHMgZm9yIHdoZW4gdGhleSBzdGFydCBtZWFzdXJpbmcuIE9ubHkgdHdvIG9ic2VydmUgdGhlIHZlcnkgYmVnaW5uaW5nIG9mIHRoZSBvdXRicmVhay4gQWxsIG9mIHRoZSBkYXRhc2V0cyBzaG93IGEgZGlzY29udGludWl0eSB3aGVyZSByZXBvcnRpbmcgc3RhbmRhcmRzIG11c3QgaGF2ZSBjaGFuZ2VkLiBPdXIgbWV0aG9kIGF0dGVtcHRzIHRvIGJyaWRnZSB0aGF0IGdhcCBpbiAzIG9mIHRoZSBzZXJpZXMgYnV0IG5vdCB0d28gb3RoZXJzLgoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFfQpwX2ludGVycG9sYXRpb24wCmBgYAojIyMjIEl0YWx5IAoKYGBge3IsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD0xMix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojSXRhbHkKIyJRMzgiCgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTM4IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgpwX2ludGVycG9sYXRpb24xIDwtIHRlc3QgJT4lCiAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgICAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIkl0YWx5IFEzOCBDb25maXJtZWQiKSArIGZhY2V0X3dyYXAofmRhdGFzZXQgICApCgpgYGAKCkl0YWx5IGxpa2V3aXNlIHNob3dzIHZhcmlhdGlvbiBpbiB0aGUgc3RhcnQgb2YgcmVjb3JkaW5nIGFjcm9zcyBkYXRhc2V0cy4gVGhlcmUncyBhbHNvIHZhcmlhdGlvbiBpbiB0aGUgaW5pdGlhbCBzcGFyY2l0eS4gV2lraXBlZGlhIGlzIHN0cmFuZ2VseSBtaXNzaW5nIGRhdGEgaW4gdGhlIG1pZGRsZS4gT3VyIG1ldGhvZCBsaW5lYXJseSBpbnRlcnBvbGF0ZXMgaW50byB0aGF0IHNwYWNlIGluIGEgd2F5IGluIGEgd2F5IHdlIHByb2JhYmx5IGRvbid0IHdhbnQuCgpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CnBfaW50ZXJwb2xhdGlvbjEKYGBgCgojIyMjIEl0YWx5IAoKYGBge3IsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD0xMix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojVVMKIyJRMzAiCgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTMwIikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgpwX2ludGVycG9sYXRpb24yIDwtIHRlc3QgJT4lCiAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgICAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIlVTIFEzMCBDb25maXJtZWQiKSArIGZhY2V0X3dyYXAofmRhdGFzZXQgICApCgpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CnBfaW50ZXJwb2xhdGlvbjIKYGBgCgoKIyMjIyBOZXcgWW9yayBTdGF0ZQoKYGBge3IsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD0xMix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojVVMKIyJRMzAiCgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTEzODQiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCnBfaW50ZXJwb2xhdGlvbjMgPC0gdGVzdCAlPiUKICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICAgICAgICAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgICAgICAgICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgICAgICAgICAgICAgICAgZ2d0aXRsZSgiTmV3IFlvcmsgU3RhdGUgUTEzODQgQ29uZmlybWVkIikgKyBmYWNldF93cmFwKH5kYXRhc2V0ICAgKQoKYGBgCgoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFfQpwX2ludGVycG9sYXRpb24zCmBgYAoKIyMjIyBOZXcgWW9yayBDaXR5IChieSBjb3VudHkpCgpueXQgaGFzIGl0IGp1c3QgYnkgY2l0eSwgaXQgZG9lc24ndCBicmVhayBpdCBkb3duIGJ5IHRoZSBib3JvdWdocy4gQnV0IGJlY2F1c2UgZ2FkbSBkb2Vzbid0IGRvIGNpdGllcyB3ZSBkb24ndCBhc3NpZ24gaXQgYSBxY29kZS4KCnVzYWZhY3RzIGhhcyBpdCBhcyBOZXcgWW9yayBDb3VudHkgd2hpY2ggaXMgTmV3IFlvcmsgQ291bnR5IChNYW5oYXR0YW4pCgpgYGB7ciwgZmlnLndpZHRoPTE2LCBmaWcuaGVpZ2h0PTEyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CiNCcm9va2x5biAoUTE4NDE5KQp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTg1NTk3NCIpICU+JSAgI25vIGhpdHM/CiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCnBfaW50ZXJwb2xhdGlvbjRhIDwtIHRlc3QgJT4lCiAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgICAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIkJyb254IENvdW50eSAoUTg1NTk3NCkiKSArIGZhY2V0X3dyYXAofmRhdGFzZXQgICApICsgZ3VpZGVzKCBjb2xvciA9IEZBTFNFKQoKI1F1ZWVucyBDb3VudHksIE5ldyBZb3JrIFE1MTQyNTU5CnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRNTE0MjU1OSIpICU+JSAgI25vIGhpdHM/CiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCnBfaW50ZXJwb2xhdGlvbjRiIDwtIHRlc3QgJT4lCiAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgICAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIlF1ZWVucyBDb3VudHksIE5ldyBZb3JrIFE1MTQyNTU5IikgKyBmYWNldF93cmFwKH5kYXRhc2V0ICAgKSArIGd1aWRlcyggY29sb3IgPSBGQUxTRSkKCiNCcm9va2x5biBpcyBhcGFyZW50bHkgS2luZ3MgQ291bnR5IFExMTk4MDY5Mgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTExOTgwNjkyIikgJT4lICAjbm8gaGl0cz8KICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCiAgICAgICAgI211dGF0ZSggY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IGJyZWFrcG9pbnRzKGZvcm11bGE9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQoKcF9pbnRlcnBvbGF0aW9uNGMgPC0gdGVzdCAlPiUKICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICAgICAgICAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgICAgICAgICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgICAgICAgICAgICAgICAgZ2d0aXRsZSgiQnJvb2tseW4gaXMgS2luZ3MgQ291bnR5IFExMTk4MDY5MiIpICsgZmFjZXRfd3JhcCh+ZGF0YXNldCAgICkgKyBndWlkZXMoIGNvbG9yID0gRkFMU0UpCgojIE1hbmhhdHRhbiBpcyBOZXcgWW9yayBDb3VudHkgUTUwMDQxNgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTUwMDQxNiIpICU+JSAgI25vIGhpdHM/CiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCnBfaW50ZXJwb2xhdGlvbjRkIDwtIHRlc3QgJT4lCiAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgICAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIk1hbmhhdHRhbiBpcyBOZXcgWW9yayBDb3VudHkgUTUwMDQxNiIpICsgZmFjZXRfd3JhcCh+ZGF0YXNldCAgICkgKyBndWlkZXMoIGNvbG9yID0gRkFMU0UpCgojU3RhdGVuIElzbGFuZCBpcyByaWNobW9uZCBjb3VudHkgUTExOTk3Nzg0CnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMTE5OTc3ODQiKSAlPiUgICNubyBoaXRzPwogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgpwX2ludGVycG9sYXRpb240ZSA8LSB0ZXN0ICU+JQogICAgICAgICAgICAgICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAgICAgICAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgICAgICAgICAgICAgICBnZ3RpdGxlKCJTdGF0ZW4gSXNsYW5kICBSaWNobW9uZCBDb3VudHkgUTExOTk3Nzg0IikgKyBmYWNldF93cmFwKH5kYXRhc2V0ICAgKSArIGd1aWRlcyggY29sb3IgPSBGQUxTRSkKCmBgYAoKTm90ZSB0aGF0IENTU0UgaXMgY29uZmxhdGluZyBhbGwgb2YgTmV3IFlvcmsgQ2l0eSB3aXRoIE1hbmhhdHRhbi9OZXcgWW9yayBDb3VudHksIEJpbmcgaXMgdG9vIEkgdGhpbmsKCmBgYHtyLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02LHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KcF9pbnRlcnBvbGF0aW9uNGEgKyBwX2ludGVycG9sYXRpb240YiArIHBfaW50ZXJwb2xhdGlvbjRjICsgcF9pbnRlcnBvbGF0aW9uNGQgKyBwX2ludGVycG9sYXRpb240ZQpgYGAKCgoKIyMgSW50ZXJwb2xhdGlvbiBvZiBSYXRlIG9mIENoYW5nZQoKIyMgUGxvdCBDb25maXJtZWQgQ3VydmVzIGZvciBTZWxlY3QgTG9jYXRpb25zCgpgYGB7ciwgZmlnLndpZHRoPTE2LCBmaWcuaGVpZ2h0PTEyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CgpsaWJyYXJ5KHBhdGNod29yaykKbGhzX2xvbmdfY2xlYW5faW1wdXRlZCA8LSByZWFkUkRTKCAiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvbGhzX2xvbmdfY2xlYW5faW1wdXRlZC5SZHMiKQpkaW0obGhzX2xvbmdfY2xlYW5faW1wdXRlZCkgIzQ1LDYwOSAjMzM3MDQzCgojd2Ugd2FudCB0aGUgY29sb3JzIHRvIGJlIGNvbnNpc3RlbnQgYnkgZGF0YXNldCB0b28gYnR3CgojIyMjIwojVVNBIFEzMAoKI2JwX3RlbXAgPC0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT10ZW1wX2RmICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSkgJT4lIGZpbHRlcih3aWtpZGF0YV9pZD09IlEzMCIpKQojY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZT1maXR0ZWQudmFsdWVzKGJwX3RlbXApCgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMzAiKSAlPiUgCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgICU+JQogICAgICAgIG11dGF0ZShkYXRlX2FzbnVtZXJpYyA9IGRhdGVfYXNkYXRlICU+JSBhcy5udW1lcmljKCkgKQoKI3J0MSA8LSBycGFydChmb3JtdWxhID0gY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IGRhdGVfYXNudW1lcmljLCBkYXRhPXRlc3QpCiNpbnRlcnBvbGF0ZWQgPSBkYXRhLmZyYW1lKGRhdGVfYXNudW1lcmljPW1pbih0ZXN0JGRhdGVfYXNudW1lcmljKTptYXgodGVzdCRkYXRlX2FzbnVtZXJpYykgKQojaW50ZXJwb2xhdGVkJGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgPC0gIHByZWRpY3QocnQxLCBuZXdkYXRhPWludGVycG9sYXRlZCkKI2ludGVycG9sYXRlZCRkYXRlX2FzZGF0ZSA8LSBhcy5EYXRlKGludGVycG9sYXRlZCRkYXRlX2FzbnVtZXJpYykKCnAwYSA8LSB0ZXN0ICU+JQogICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgICAgZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgICBnZ3RpdGxlKCJVU0EgUTMwIENvbmZpcm1lZCIpICMgKyBmYWNldF93cmFwKH5kYXRhc2V0KSAKCnAwYiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMyApICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIgICkgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgIGdndGl0bGUoIlVTQSBRMzAgQ29uZmlybWVkIikgIyArIGZhY2V0X3dyYXAofmRhdGFzZXQpKyB5bGFiKCJEYWlseSBQZXJjZW50IENoYW5nZSBDb25maXJtZWQiKQoKI3AwYSAvIHAwYgoKCgojIyMjIwojQ2hpbmEgUTE0OAoKdGVzdCA8LSBsaHNfbG9uZ19jbGVhbl9pbXB1dGVkICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMTQ4IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKCnAxYSA8LSB0ZXN0ICU+JSAKZ2dwbG90KCkgKyAKICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiQ2hpbmEgUTE0OCBDb25maXJtZWQiKQoKcDFiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiQ2hpbmEgUTE0OCBDb25maXJtZWQiKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgQ29uZmlybWVkIikKICAgCgojcDFhIC8gcDFiCgojSW5kaWEKIyJRNjY4IgoKdGVzdCA8LSBsaHNfbG9uZ19jbGVhbl9pbXB1dGVkICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSkgJT4lIGZpbHRlcih3aWtpZGF0YV9pZD09IlE2NjgiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCgpwMmEgPC0gdGVzdCAlPiUKZ2dwbG90KCkgKyAKICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiSW5kaWEgUTY2OCBDb25maXJtZWQiKQoKcDJiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiSW5kaWEgUTY2OCBDb25maXJtZWQiKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgQ29uZmlybWVkIikKIAogIAojcDJhIC8gcDJiCgoKCiNJdGFseQojIlEzOCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMzgiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCgpwNGEgPC0gdGVzdCAlPiUKZ2dwbG90KCkgKyAKICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiSXRhbHkgUTM4IENvbmZpcm1lZCIpCgpwNGIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIpICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJJdGFseSBRMzggQ29uZmlybWVkIikrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIENvbmZpcm1lZCIpCiAgIAogICAgCiNwNGEgLyBwNGIKCgoKI1NvdXRoIEtvcmVhCiMiUTg4NCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRODg0IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgoKcDVhIDwtIHRlc3QgJT4lCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIlNvdXRoIEtvcmVhIFE4ODQgIENvbmZpcm1lZCIpCgpwNWIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIpICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJTb3V0aCBLb3JlYSBRODg0IENvbmZpcm1lZCIpICsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgQ29uZmlybWVkIikKICAgCiAgICAKI3A1YSAvIHA1YgpgYGAKCgoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02ICx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CihwMGEgKyBwMWEgKyBwMmEgKSAvIChwMGIgKyBwMWIgKyBwMmIgKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9NiAsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFfQooIHA0YSArIHA1YSkgLyAoIHA0YiArIHA1YikKYGBgCgpgYGB7cn0KCgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTE0MzkiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCgpwMGEgPC0gdGVzdCAlPiUKICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiVGV4YXMgUTE0MzkgQ29uZmlybWVkIikKCnAwYiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgKSwgYWxwaGE9MSwgY29sb3I9ImJsYWNrIikgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgIGdndGl0bGUoIlRleGFzIFExNDM5IENvbmZpcm1lZCIpICsgeWxpbSgwLDEwMCkrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIENvbmZpcm1lZCIpCgojQmV4YXIKIyJRMTY4NjEiCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMTY4NjEiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKcDFhIDwtIHRlc3QgJT4lCiAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgIGdndGl0bGUoIkJleGFyIENvdW50eSBRMTY4NjEgQ29uZmlybWVkIikKcDFiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiQmV4YXIgQ291bnR5IFExNjg2MSBDb25maXJtZWQiKSArIHlsaW0oMCwxMDApKyB5bGFiKCJEYWlseSBQZXJjZW50IENoYW5nZSBDb25maXJtZWQiKQoKI0NhbGlmb3JuaWEKdGVzdCA8LSBsaHNfbG9uZ19jbGVhbl9pbXB1dGVkICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSkgJT4lIGZpbHRlcih3aWtpZGF0YV9pZD09IlE5OSIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCiAgICAgICAgI211dGF0ZSggY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IGJyZWFrcG9pbnRzKGZvcm11bGE9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQpwMmEgPC0gdGVzdCAlPiUKICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiQ2FsaWZvcm5pYSBROTkgQ29uZmlybWVkIikKcDJiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiQ2FsaWZvcm5pYSBROTkgQ29uZmlybWVkIikgKyB5bGltKDAsMTAwKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgQ29uZmlybWVkIikKCiNTYW4gRGllZ28gQ291bnR5IChRMTA4MTQzKQp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTEwODE0MyIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCiAgICAgICAgI211dGF0ZSggY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IGJyZWFrcG9pbnRzKGZvcm11bGE9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQpwM2EgPC0gdGVzdCAlPiUKICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiU2FuIERpZWdvIENvdW50eSAoUTEwODE0MykgQ29uZmlybWVkIikKcDNiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiU2FuIERpZWdvIENvdW50eSAoUTEwODE0MykgQ29uZmlybWVkIikgKyB5bGltKDAsMTAwKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgQ29uZmlybWVkIikKCiNGbG9yaWRhIChRODEyKQp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTgxMiIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsY29uZmlybWVkX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCiAgICAgICAgI211dGF0ZSggY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IGJyZWFrcG9pbnRzKGZvcm11bGE9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQpwNGEgPC0gdGVzdCAlPiUKICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiRmxvcmlkYSAoUTgxMikgQ29uZmlybWVkIikKcDRiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9Y29uZmlybWVkX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiRmxvcmlkYSAoUTgxMikgQ29uZmlybWVkIikgKyB5bGltKDAsMTAwKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgQ29uZmlybWVkIikKCgojU3QuIEx1Y2llIENvdW50eSAoUTQ5NDU2NCkKdGVzdCA8LSBsaHNfbG9uZ19jbGVhbl9pbXB1dGVkICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSkgJT4lIGZpbHRlcih3aWtpZGF0YV9pZD09IlE0OTQ1NjQiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGNvbmZpcm1lZF9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKcDVhIDwtIHRlc3QgJT4lCiAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgIGdndGl0bGUoIlN0LiBMdWNpZSBDb3VudHkgKFE0OTQ1NjQpIENvbmZpcm1lZCIpCnA1YiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgKSwgYWxwaGE9MSwgY29sb3I9ImJsYWNrIikgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgIGdndGl0bGUoIlN0LiBMdWNpZSBDb3VudHkgKFE0OTQ1NjQpIENvbmZpcm1lZCIpICsgeWxpbSgwLDEwMCkrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIENvbmZpcm1lZCIpCgoKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTYgLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KI05vdCBjb3VudGluZyBzbG9wZXMgdGhhdCB3ZXJlIGludGVycG9sYXRlZCBvdXQgb2YgZG9tYWluIGZpeGVkIGNhbGlmb3JuaWEncyBwbG90CiggcDBhICsgcDFhICkgLyAoIHAwYiArIHAxYiApCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02ICx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CiggcDJhICsgcDNhICkgLyAoIHAyYiArIHAzYiApCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02ICx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CiggcDRhICsgcDVhKSAvICggcDRiICsgcDViKQpgYGAKCgojIyBQbG90IERlYXRoIEN1cnZlcyBmb3IgU2VsZWN0IExvY2F0aW9ucwoKU2hvdyBob3cgaW50ZXJwb2xhdGlvbiB3b3JrcyBvbiBkZWF0aHMKCmBgYHtyLCBmaWcud2lkdGg9MTYsIGZpZy5oZWlnaHQ9MTIsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxkZWF0aHNfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGZpbHRlcih3aWtpZGF0YV9pZD09IlEzMCIpICU+JSAKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAgJT4lCiAgICAgICAgbXV0YXRlKGRhdGVfYXNudW1lcmljID0gZGF0ZV9hc2RhdGUgJT4lIGFzLm51bWVyaWMoKSApCgpwMGEgPC0gdGVzdCAlPiUKICAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9ZGVhdGhzX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgICAgZ2d0aXRsZSgiVVNBIFEzMCBEZWF0aHMiKSAjICsgZmFjZXRfd3JhcCh+ZGF0YXNldCkgCgpwMGIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMgKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9ZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siICApICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9ZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHNfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICBnZ3RpdGxlKCJVU0EgUTMwIERlYXRocyIpICsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgRGVhdGhzIikgIyArIGZhY2V0X3dyYXAofmRhdGFzZXQpCgojcDBhIC8gcDBiCgoKIyMjIyMKI0NoaW5hIFExNDgKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsZGVhdGhzX2xvZ19ncm91cF9udW1iZXIpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTE0OCIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsZGVhdGhzX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCgpwMWEgPC0gdGVzdCAlPiUgCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIkNoaW5hIFExNDggRGVhdGhzIikKCnAxYiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgKSwgYWxwaGE9MSwgY29sb3I9ImJsYWNrIikgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIkNoaW5hIFExNDggRGVhdGhzIikrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIERlYXRocyIpCiAgIAoKI3AxYSAvIHAxYgoKI0luZGlhCiMiUTY2OCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRNjY4IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxkZWF0aHNfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBkZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgoKcDJhIDwtIHRlc3QgJT4lCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIkluZGlhIFE2NjggRGVhdGhzIikKCnAyYiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PWRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgKSwgYWxwaGE9MSwgY29sb3I9ImJsYWNrIikgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIkluZGlhIFE2NjggRGVhdGhzIikrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIERlYXRocyIpCiAKICAKI3AyYSAvIHAyYgoKI0JleGFyCiMiUTE2ODYxIgoKdGVzdCA8LSBsaHNfbG9uZ19jbGVhbl9pbXB1dGVkICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCxkZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSkgJT4lIGZpbHRlcih3aWtpZGF0YV9pZD09IlExNjg2MSIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsZGVhdGhzX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCiAgICAgICAgI211dGF0ZSggZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IGJyZWFrcG9pbnRzKGZvcm11bGE9ZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQoKCnAzYSA8LSB0ZXN0ICU+JQogICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHNfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHNfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICBnZ3RpdGxlKCJCZXhhciBDb3VudHkgUTE2ODYxIERlYXRocyIpCgpwM2IgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIpICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9ZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHNfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJCZXhhciBDb3VudHkgUTE2ODYxIERlYXRocyIpICsgeWxpbSgwLDEwMCkrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIERlYXRocyIpCiAgIAojcDNhIC8gcDNiCgoKCiNJdGFseQojIlEzOCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMzgiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLGRlYXRoc19sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIGRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPWRlYXRoc19sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCgpwNGEgPC0gdGVzdCAlPiUKZ2dwbG90KCkgKyAKICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9ZGVhdGhzX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9ZGVhdGhzX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiSXRhbHkgUTM4IERlYXRocyIpCgpwNGIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIpICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9ZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHNfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJJdGFseSBRMzggRGVhdGhzIikrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIERlYXRocyIpCiAgIAogICAgCiNwNGEgLyBwNGIKCgoKI1NvdXRoIEtvcmVhCiMiUTg4NCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRODg0IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCxkZWF0aHNfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCBkZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgoKcDVhIDwtIHRlc3QgJT4lCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRoc19sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIlNvdXRoIEtvcmVhIFE4ODQgIERlYXRocyIpCgpwNWIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT1kZWF0aHNfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIpICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9ZGVhdGhzX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHNfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJTb3V0aCBLb3JlYSBRODg0IERlYXRocyIpICsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgRGVhdGhzIikKICAgCiAgICAKI3A1YSAvIHA1YgpgYGAKCkkgbmVlZCB0byBmaXggdGhpcywgVVNBIGhhcyBhIGZyYWN0aW9uIG9mIGEgZGVhdGgKCk5vdGUgdGhlIGRpc2NvbnRpbnVpdHkgaW4gQ2hpbiB3aGVuIHRoZXkgYWRkZWQgdGhvc2UgMWsgZGVhdGhzIHRvIHRoZSB0b3RhbAoKSW5kaWEgZGVhdGhzIGlzIGJyb2tlbiwgd2Ugc2hvdWxkbid0IGJlIGludGVycG9sYXRpbmcgYSByYXRlIGJlZm9yZSB3ZSB0aGluayB0aGUgbnVtYmVyIGlzIGdyZWF0ZXIgdGhhbiAwCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTYgLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KKHAwYSArIHAxYSArIHAyYSApIC8gKHAwYiArIHAxYiArIHAyYiApCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02ICx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CihwM2EgKyBwNGEgKyBwNWEpIC8gKHAzYiArIHA0YiArIHA1YikKYGBgCgoKCiMjIFBsb3QgVGVzdGluZyBDdXJ2ZXMgZm9yIFNlbGVjdCBMb2NhdGlvbnMKClNob3cgaG93IGludGVycG9sYXRpb24gd29ya3Mgb24gdGVzdGVkCgpVUyBpcyBhbiBleGFtcGxlIHdoZXJlIHdlIGludGVycG9sYXRlZCBwYXN0IG91ciBhdmFpbGFibGUgZGF0YS4gU2hvdWxkbid0IGRvIHRoYXQgZWl0aGVyIQpgYGB7ciwgZmlnLndpZHRoPTE2LCBmaWcuaGVpZ2h0PTEyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9Cgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsdGVzdGVkX3Blb3BsZV9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTMwIikgJT4lIAogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICAlPiUKICAgICAgICBtdXRhdGUoZGF0ZV9hc251bWVyaWMgPSBkYXRlX2FzZGF0ZSAlPiUgYXMubnVtZXJpYygpICkKCnAwYSA8LSB0ZXN0ICU+JQogICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICAgIHRoZW1lX2J3KCkgKwogICAgICAgICAgIGdndGl0bGUoIlVTQSBRMzAgVGVzdGVkIikgICMrIGZhY2V0X3dyYXAofmRhdGFzZXQpIAoKcDBiIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMyApICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siICApICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgIGdndGl0bGUoIlVTQSBRMzAgdGVzdGVkX3Blb3BsZSIpICsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgdGVzdGVkX3Blb3BsZSIpICMgKyBmYWNldF93cmFwKH5kYXRhc2V0KQoKI3AwYSAvIHAwYgoKCiMjIyMjCiNDaGluYSBRMTQ4Cgp0ZXN0IDwtIGxoc19sb25nX2NsZWFuX2ltcHV0ZWQgJT4lIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LHdpa2lkYXRhX2lkLHRlc3RlZF9wZW9wbGVfbG9nX2dyb3VwX251bWJlcikpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMTQ4IikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCx0ZXN0ZWRfcGVvcGxlX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCgpwMWEgPC0gdGVzdCAlPiUgCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXRlc3RlZF9wZW9wbGVfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiQ2hpbmEgUTE0OCB0ZXN0ZWRfcGVvcGxlIikKCnAxYiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJDaGluYSBRMTQ4IHRlc3RlZF9wZW9wbGUiKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgdGVzdGVkX3Blb3BsZSIpCiAgIAoKI3AxYSAvIHAxYgoKI0luZGlhCiMiUTY2OCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTY2OCIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsdGVzdGVkX3Blb3BsZV9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIHRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQoKCnAyYSA8LSB0ZXN0ICU+JQpnZ3Bsb3QoKSArIAogICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT10ZXN0ZWRfcGVvcGxlX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIkluZGlhIFE2NjggdGVzdGVkX3Blb3BsZSIpCgpwMmIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgKSwgYWxwaGE9MSwgY29sb3I9ImJsYWNrIikgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiSW5kaWEgUTY2OCB0ZXN0ZWRfcGVvcGxlIikrIHlsYWIoIkRhaWx5IFBlcmNlbnQgQ2hhbmdlIHRlc3RlZF9wZW9wbGUiKQogCiAgCiNwMmEgLyBwMmIKCiNCZXhhcgojIlExNjg2MSIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTE2ODYxIikgJT4lIAogICAgICAgIG11dGF0ZShncm91cD1wYXN0ZShkYXRhc2V0LCB3aWtpZGF0YV9pZCx0ZXN0ZWRfcGVvcGxlX2xvZ19ncm91cF9udW1iZXIpKSAlPiUKICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAjJT4lCiAgICAgICAgI211dGF0ZSggdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgPSBicmVha3BvaW50cyhmb3JtdWxhPXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlIH4gMSwgZGF0YT0uICkgJT4lIGZpdHRlZC52YWx1ZXMoKSApCgoKcDNhIDwtIHRlc3QgJT4lCiAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXRlc3RlZF9wZW9wbGVfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgZ2d0aXRsZSgiQmV4YXIgQ291bnR5IFExNjg2MSB0ZXN0ZWRfcGVvcGxlIikKCnAzYiA8LSB0ZXN0ICU+JQogICAgICAgZ2dwbG90KCkgKyAKICAgICAgICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgICAgICAgZ2VvbV9saW5lKGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCApLCBhbHBoYT0xLCBjb2xvcj0iYmxhY2siKSArCiAgICAgICAgICNnZW9tX3Ntb290aCggYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlKSwgYWxwaGE9LjMsIHNwYW49LjA1KSArICMsIHNwYW49LjA1CiAgICAgICAgICNnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAgICAgICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICAgICAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJCZXhhciBDb3VudHkgUTE2ODYxIHRlc3RlZF9wZW9wbGUiKSArIHlsaW0oMCwxMDApKyB5bGFiKCJEYWlseSBQZXJjZW50IENoYW5nZSB0ZXN0ZWRfcGVvcGxlIikKICAgCiNwM2EgLyBwM2IKCgoKI0l0YWx5CiMiUTM4IgoKdGVzdCA8LSBsaHNfbG9uZ19jbGVhbl9pbXB1dGVkICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCx3aWtpZGF0YV9pZCx0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSkpICU+JSBmaWx0ZXIod2lraWRhdGFfaWQ9PSJRMzgiKSAlPiUgCiAgICAgICAgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsIHdpa2lkYXRhX2lkLHRlc3RlZF9wZW9wbGVfbG9nX2dyb3VwX251bWJlcikpICU+JQogICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICMlPiUKICAgICAgICAjbXV0YXRlKCB0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSA9IGJyZWFrcG9pbnRzKGZvcm11bGE9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UgfiAxLCBkYXRhPS4gKSAlPiUgZml0dGVkLnZhbHVlcygpICkKCgpwNGEgPC0gdGVzdCAlPiUKZ2dwbG90KCkgKyAKICAgZ2VvbV9wb2ludCggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICBnZW9tX2xpbmUoIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0LCBjb2xvcj1kYXRhc2V0LCBncm91cD1ncm91cCkpICsgIwogICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJJdGFseSBRMzggdGVzdGVkX3Blb3BsZSIpCgpwNGIgPC0gdGVzdCAlPiUKICAgICAgIGdncGxvdCgpICsgCiAgICAgICAgIGdlb21fcG9pbnQoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgICAgICAgIGdlb21fbGluZShhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQgKSwgYWxwaGE9MSwgY29sb3I9ImJsYWNrIikgKwogICAgICAgICAjZ2VvbV9zbW9vdGgoIGFlcyh4PWRhdGVfYXNkYXRlICwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSksIGFscGhhPS4zLCBzcGFuPS4wNSkgKyAjLCBzcGFuPS4wNQogICAgICAgICAjZ2VvbV9saW5lKCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXApKSArICMKICAgICAgICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgICAgICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiSXRhbHkgUTM4IHRlc3RlZF9wZW9wbGUiKSsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgdGVzdGVkX3Blb3BsZSIpCiAgIAogICAgCiNwNGEgLyBwNGIKCgoKI1NvdXRoIEtvcmVhCiMiUTg4NCIKCnRlc3QgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKGRhdGFzZXQsd2lraWRhdGFfaWQsdGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTg4NCIpICU+JSAKICAgICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUoZGF0YXNldCwgd2lraWRhdGFfaWQsdGVzdGVkX3Blb3BsZV9sb2dfZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgIyU+JQogICAgICAgICNtdXRhdGUoIHRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlID0gYnJlYWtwb2ludHMoZm9ybXVsYT10ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKQoKCnA1YSA8LSB0ZXN0ICU+JQpnZ3Bsb3QoKSArIAogICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT10ZXN0ZWRfcGVvcGxlX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS4zKSArCiAgIGdlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIlNvdXRoIEtvcmVhIFE4ODQgIHRlc3RlZF9wZW9wbGUiKQoKcDViIDwtIHRlc3QgJT4lCiAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICBnZW9tX3BvaW50KCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UsIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICAgICAgICBnZW9tX2xpbmUoYWVzKHg9ZGF0ZV9hc2RhdGUgLCB5PXRlc3RlZF9wZW9wbGVfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0ICksIGFscGhhPTEsIGNvbG9yPSJibGFjayIpICsKICAgICAgICAgI2dlb21fc21vb3RoKCBhZXMoeD1kYXRlX2FzZGF0ZSAsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2UpLCBhbHBoYT0uMywgc3Bhbj0uMDUpICsgIywgc3Bhbj0uMDUKICAgICAgICAgI2dlb21fbGluZSggYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9dGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwKSkgKyAjCiAgICAgICAgICNnZW9tX2xpbmUoZGF0YT10ZW1wX2RmMiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXRfbWVhbiksIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgICAgICAgdGhlbWVfYncoKSArCiAgIGdndGl0bGUoIlNvdXRoIEtvcmVhIFE4ODQgdGVzdGVkX3Blb3BsZSIpICsgeWxhYigiRGFpbHkgUGVyY2VudCBDaGFuZ2UgdGVzdGVkX3Blb3BsZSIpCiAgIAogICAgCiNwNWEgLyBwNWIKYGBgCgpJIG5lZWQgdG8gZml4IHRoaXMsIFVTQSBoYXMgYSBmcmFjdGlvbiBvZiBhIGRlYXRoCgpOb3RlIHRoZSBkaXNjb250aW51aXR5IGluIENoaW4gd2hlbiB0aGV5IGFkZGVkIHRob3NlIDFrIGRlYXRocyB0byB0aGUgdG90YWwKCkluZGlhIGRlYXRocyBpcyBicm9rZW4sIHdlIHNob3VsZG4ndCBiZSBpbnRlcnBvbGF0aW5nIGEgcmF0ZSBiZWZvcmUgd2UgdGhpbmsgdGhlIG51bWJlciBpcyBncmVhdGVyIHRoYW4gMAoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02ICx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0V9CihwMGEgKyBwMWEgKyBwMmEgKSAvIChwMGIgKyBwMWIgKyBwMmIgKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9NiAsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFfQoocDNhICsgcDRhICsgcDVhKSAvIChwM2IgKyBwNGIgKyBwNWIpCmBgYAoKCiMgQWxpZ25pbmcgQ3VydmVzIGJ5IFRha2VvZmYKCmBgYHtyLCBlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CgpkZl9zbG9wZXMgPC0gbGhzX2xvbmdfY2xlYW5faW1wdXRlZCAlPiUgCiAgICAgICAgICAgICBncm91cF9ieShnaWQsIGdlb25hbWVpZCwgd2lraWRhdGFfaWQsIGRhdGVfYXNkYXRlKSAlPiUgCiAgICAgICAgICAgICBtdXRhdGUoCiAgICAgICAgICAgICAgICAgICAgY29uZmlybWVkPW1lZGlhbihjb25maXJtZWQsIG5hLnJtPVQpLAogICAgICAgICAgICAgICAgICAgIGRlYXRocz1tZWRpYW4oZGVhdGhzLCBuYS5ybT1UKSwKICAgICAgICAgICAgICAgICAgICB0ZXN0ZWRfcGVvcGxlPW1lZGlhbih0ZXN0ZWRfcGVvcGxlLCBuYS5ybT1UKSwKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBjb25maXJtZWRfbG9nX3lfaGF0PW1lZGlhbihjb25maXJtZWRfbG9nX3lfaGF0LCBuYS5ybT1UKSwKICAgICAgICAgICAgICAgICAgICBkZWF0aHNfbG9nX3lfaGF0PW1lZGlhbihkZWF0aHNfbG9nX3lfaGF0LCBuYS5ybT1UKSwKICAgICAgICAgICAgICAgICAgICB0ZXN0ZWRfcGVvcGxlX2xvZ195X2hhdD1tZWRpYW4odGVzdGVkX3Blb3BsZV9sb2dfeV9oYXQsIG5hLnJtPVQpLAogICAgICAgICAgICAgICAgICAgICkgJT4lCiAgICAgICAgICAgICB1bmdyb3VwKCkgJT4lCiAgICAgICAgICAgICBncm91cF9ieShnaWQsIGdlb25hbWVpZCwgd2lraWRhdGFfaWQpICU+JSAKICAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICU+JSAKICAgICAgICAgICAgIGZpbHRlcighZHVwbGljYXRlZChkYXRlX2FzZGF0ZSkpICU+JSAKICAgICAgICAgICAgIG11dGF0ZSh0ID0gcm93X251bWJlcigpKSAlPiUKICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0X2ZkPXRzaWJibGU6OmRpZmZlcmVuY2UoY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCkpICU+JQogIAogICAgICAgICAgICAgI1NvIHRoZXJlIGFyZSBvbmVzIHRoYXQgc3RhcnQgbG93IGFuZCBidWlsZCB1cAogICAgICAgICAgICAgbXV0YXRlKHRfYWxsaWduZWRfbWF4ZmQgPSAgY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdF9mZD09bWF4KGNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXRfZmQsbmEucm09VCkgKSAlPiUgCiAgICAgICAgICAgICAjYnV0IHRoZXJlIGFyZSBvdGhlciBvbmVzIHRoYXQgZ28gZnJvbSB6ZXJvIHRvIGhpZ2ggYW5kIHRob3NlIGFyZW4ndCBnZXR0aW5nIGNhdWdodCBieSB0aGUgdG9wIGFib3ZlCiAgICAgICAgICAgICBtdXRhdGUodF9hbGxpZ25lZF9tYXhfYXRfMCA9ICBjb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0PT1tYXgoY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCxuYS5ybT1UKSAmIHQ9PTEgKSAlPiUgCgogICAgICAgICAgICAgbXV0YXRlKHRfYWxsaWduZWQgPSBpZmVsc2UodF9hbGxpZ25lZF9tYXhfYXRfMCB8ICh0X2FsbGlnbmVkX21heGZkICYgbWF4KHRfYWxsaWduZWRfbWF4X2F0XzApPT1GKSAsIHQsIE5BKSApICU+JSAKICAgICAgICAgICAgIG11dGF0ZSh0X2FsbGlnbmVkID0gbWF4KHRfYWxsaWduZWQsIG5hLnJtPVQpICkgJT4lCiAgICAgICAgICAgICBtdXRhdGUodF9hbGxpZ25lZCA9IHQtbWF4KHRfYWxsaWduZWQsIG5hLnJtPVQpICkgJT4lCgogICAgICAgICAgICAgbXV0YXRlKHRfYWxsaWduZWRfZmlyc3Rjb25maXJtZWQgPSBpZmVsc2UoY29uZmlybWVkPT1taW4oY29uZmlybWVkLCBuYS5ybT1UKSAsIHQsIE5BKSApICU+JSAKICAgICAgICAgICAgIG11dGF0ZSh0X2FsbGlnbmVkX2ZpcnN0Y29uZmlybWVkID0gbWF4KHRfYWxsaWduZWRfZmlyc3Rjb25maXJtZWQsIG5hLnJtPVQpICkgJT4lCiAgICAgICAgICAgICBtdXRhdGUodF9hbGxpZ25lZF9maXJzdGNvbmZpcm1lZCA9IHQtbWF4KHRfYWxsaWduZWRfZmlyc3Rjb25maXJtZWQsIG5hLnJtPVQpICkgJT4lCgogICAgICAgICAgICAgI3RoaXMgdGhyb3dzIGEgYnVuY2ggb2YgaW5maW5pdGUgbWlzc2luZyBiZWNhdXNlIG9mIGNvdW50cmllcyB0aGF0IGhhdmVuJ3QgeWV0IGhpdCAxMDAKICAgICAgICAgICAgICNtdXRhdGUodF9hbGxpZ25lZF8xMDBjb25maXJtZWRfMTAwID0gaWZlbHNlKGNvbmZpcm1lZD49MTAwICAsIHQsIE5BKSApICU+JSAKICAgICAgICAgICAgICNtdXRhdGUodF9hbGxpZ25lZF8xMDBjb25maXJtZWRfMTAwID0gaWZlbHNlKHRfYWxsaWduZWRfMTAwY29uZmlybWVkXzEwMD09bWluKHRfYWxsaWduZWRfMTAwY29uZmlybWVkXzEwMCwgbmEucm09VCkgLCB0LCBOQSkgKSAlPiUgCiAgICAgICAgICAgICAjbXV0YXRlKHRfYWxsaWduZWRfMTAwY29uZmlybWVkID0gdC1tYXgodF9hbGxpZ25lZF8xMDBjb25maXJtZWRfMTAwLCBuYS5ybT1UKSApICU+JQogICAgICAgICAgICAgI2RwbHlyOjpzZWxlY3QoLXRfYWxsaWduZWRfMTAwY29uZmlybWVkXzEwMCkgJT4lCiAgICAgICAgICAgICB1bmdyb3VwKCkKYGBgCgpgYGB7ciwgZXZhbD1GfQoKbGlicmFyeShpbmZvdGhlbykKI09uY2Ugd2UgcmVtb3ZlZCB0aGUgbm8gdmFyaWFuY2UgcGxhY2VzIG15IGFsaWdubWVudCBoYXMgbW9yZSBtdXR1YWwgaW5mb3JtYXRpb24gdGhhbiBlaXRoZXIgZmlyc3QgY29uZmlybWVkIG9yIDEwMCBjb25maXJtZWQKbXV0aW5mb3JtYXRpb24oWD1kZl9zbG9wZXMgJT4lIGRwbHlyOjpzZWxlY3QodCx0X2FsbGlnbmVkLHRfYWxsaWduZWRfZmlyc3Rjb25maXJtZWQsY29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCkgJT4lIGRpc2NyZXRpemUoKSwgbWV0aG9kPSJlbXAiKSAjd2Ugb3V0cGVyZm9ybWVkIHRfYWxsaWduZWRfMTAwY29uZmlybWVkIGJ1dCBpdCB3YXNuJ3QgYXZhaWwgZm9yIG1vc3QKCiNkZl9zbG9wZXMgJT4lIGZpbHRlcihhYnModF9hbGxpZ25lZCk8MjAsYWJzKHRfYWxsaWduZWRfMTAwY29uZmlybWVkXzEwMCk8MjApICU+JSBqYW5pdG9yOjp0YWJ5bCh0X2FsbGlnbmVkLCB0X2FsbGlnbmVkXzEwMGNvbmZpcm1lZF8xMDApCiNoaXN0KGRmX3Nsb3BlcyR0X2FsbGlnbmVkIC0gZGZfc2xvcGVzJHRfYWxsaWduZWRfMTAwY29uZmlybWVkXzEwMCwgYnJlYWtzPTUwKQogIApgYGAKClBsb3Qgb2YgY3VydmVzIHJhdyBhbmQgdGhlbiBjdXJ2ZXMgYWxsaWduZWQgYnkgdGFrZW9mZiBzdGFydAoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMiwgZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQoKI2RmX3Nsb3BlcyAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKHdpa2lkYXRhX2lkKSkgJT4lCiMgICAgICAgICAgICAgIGdncGxvdCgpICsgCiMgICAgICAgICAgICAgIGdlb21fbGluZSggYWVzKHg9dF9hbGxpZ25lZCAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCwgZ3JvdXA9d2lraWRhdGFfaWQpLCBhbHBoYT0uMDUsIGNvbG9yPSJibHVlIikgKwojICAgICAgICAgICAgICB0aGVtZV9idygpICsKIyAgICAgICAgICAgICAgZ2d0aXRsZSgiSW50ZXJwb2xhdGVkIGxvZyBjb3VudCBieSBBbGxpZ25lZCBUIikgKyB5bGltKDAsMTAwKQoKCnBfdF9hbGxpZ25lZF9maXJzdGNvbmZpcm1lZCA8LSAgZGZfc2xvcGVzICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUod2lraWRhdGFfaWQpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKCBhZXMoeD10X2FsbGlnbmVkX2ZpcnN0Y29uZmlybWVkICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0LCBncm91cD1ncm91cCwgY29sb3I9d2lraWRhdGFfaWQpLCBhbHBoYT0xKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV9idygpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIkludGVycG9sYXRlZCBsb2cgY291bnQgYnkgVCIpICsgeWxpbSgwLDEwMCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2doaWdobGlnaHQod2lraWRhdGFfaWQgJWluJSBjKCdRMzAnLCdRMTQzOScsJ1E2NjgnLCdRODg0JywnUTE2ODYxJywnUTE1OScsJ1EzOCcpLCB1bmhpZ2hsaWdodGVkX3BhcmFtcz1saXN0KGFscGhhPS4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3Ntb290aCggYWVzKHg9dF9hbGxpZ25lZF9maXJzdGNvbmZpcm1lZCAsIHk9Y29uZmlybWVkX2xvZ195X2hhdF9wZXJjZW50X2NoYW5nZV95X2hhdCksIHNwYW4gPSAwLjA1KSAgKyB4bGltKC01MCwxMDApCgojcF90X2FsbGlnbmVkX2ZpcnN0Y29uZmlybWVkCgoKcF90X2FsbGlnbmVkIDwtIGRmX3Nsb3BlcyAlPiUgbXV0YXRlKGdyb3VwPXBhc3RlKHdpa2lkYXRhX2lkKSkgJT4lIAogICAgICAgICAgICAgICBnZ3Bsb3QoKSArIAogICAgICAgICAgICAgICBnZW9tX2xpbmUoIGFlcyh4PXRfYWxsaWduZWQgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQsIGdyb3VwPWdyb3VwLCBjb2xvcj13aWtpZGF0YV9pZCksIGFscGhhPTEpICsKICAgICAgICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgICAgICAgIGdndGl0bGUoIkludGVycG9sYXRlZCBsb2cgY291bnQgYnkgQWxsaWduZWQgVCIpICsgeWxpbSgwLDEwMCkgKwogICAgICAgICAgICAgICBnZ2hpZ2hsaWdodCh3aWtpZGF0YV9pZCAlaW4lIGMoJ1EzMCcsJ1ExNDM5JywnUTY2OCcsJ1E4ODQnLCdRMTY4NjEnLCdRMTU5JywnUTM4JyksIHVuaGlnaGxpZ2h0ZWRfcGFyYW1zPWxpc3QoYWxwaGE9LjEpKSArCiAgICAgICAgICAgICAgIGdlb21fc21vb3RoKCBhZXMoeD10X2FsbGlnbmVkICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0KSwgc3BhbiA9IDAuMDUpICsgeGxpbSgtNTAsMTAwKQoKI3BfdF9hbGxpZ25lZAojZGZfc2xvcGVzICU+JSBtdXRhdGUoZ3JvdXA9cGFzdGUod2lraWRhdGFfaWQpKSAlPiUgCiNnZ3Bsb3QoKSArIAojICAgZ2VvbV9saW5lKCBhZXMoeD10X2FsbGlnbmVkICwgeT1jb25maXJtZWRfbG9nX3lfaGF0X3BlcmNlbnRfY2hhbmdlX3lfaGF0LCBncm91cD1ncm91cCwgY29sb3I9d2lraWRhdGFfaWQpLCBhbHBoYT0xKSArCiMgICB0aGVtZV9idygpICsKIyAgIGdndGl0bGUoIkludGVycG9sYXRlZCBsb2cgY291bnQgYnkgQWxsaWduZWQgVCIpICsgeWxpbSgwLDEwMCkgICsgeGxpbSgwLDEwMCkgKwojICAgZ2doaWdobGlnaHQod2lraWRhdGFfaWQgJWluJSBjKCdRMzAnLCdRMTQzOScsJ1E2NjgnLCdRODg0JywnUTE2ODYxJywnUTE1OScsJ1EzOCcpLCB1bmhpZ2hsaWdodGVkX3BhcmFtcz1saXN0KGFscGhhPS4xKSkgKwojICAgZ2VvbV9zbW9vdGgoIGFlcyh4PXRfYWxsaWduZWQgLCB5PWNvbmZpcm1lZF9sb2dfeV9oYXRfcGVyY2VudF9jaGFuZ2VfeV9oYXQpLCBzcGFuID0gMC4wNSkgCgoKCmBgYAoKVGhlIGlkZWEgaGVyZSBpcyB0aGF0IGNvbXBsZXRlbHkgdW5jb25zdHJhaW5lZCwgQ09WSUQtMTkgZ3Jvd3RoIHNob3VsZCBmb2xsb3cgYSBsb2dpc3RpYyBjdXJ2ZSwgZmxhdCwgdXBzd2luZywgY29uc3RhbnQgZ3Jvd3RoLCBkb3duc3dpbmcsIGFuZCBmbGF0IGFnYWluLiBUaGUgYXNzdW1wdGlvbiBvZiBubyB1bmNvbnN0cmFpbmVkIGdyb3d0aCBubyBsb25nZXIgaG9sZHMgYmVjYXVzZSB0aGUgd29ybGQgaXMgcmVhY3RpbmcsIGJ1dCB0aGVyZSdzIHN0aWxsIGEgcHJldHR5IHVuaWZvcm1seSBjaGFyYWN0ZXJpc3RpYyB1cHN3aW5nIGFjcm9zcyBnZW9ncmFwaGljIHVuaXRzLiBXZSBsb29rIGZvciB0aGlzIHNpZ25hbCBvZiB0aGUgbGFyZ2VzdCBmaXJzdCBkaWZmZXJlbmNlIGluIHRoZSBkYWlseSBwZXJjZW50IGNoYW5nZSwgY2FsbCB0aGF0IHRoZSB0YWtlb2ZmIGRhdGUsIGFuZCB0aGVuIGFsbGlnbiBhbGwgdGhlIHRpbWUgc2VyaWVzIHdpdGggdGhhdCBkYXRlIGFzIDAuCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KcF90X2FsbGlnbmVkX2ZpcnN0Y29uZmlybWVkICAvIHBfdF9hbGxpZ25lZCAKYGBgCgoKV2hhdCB0aGlzIGdpdmVzIHVzIGlzIGEgbmljZSBub3JtYWxpemVkIGRhdGFzZXQgd2hlcmUgdGhlIHRhc2sgaXMgdG8gcHJlZGljdCB0aGUgc2hhcGUgb2YgdGhhdCBkaXN0cmlidXRpb24uIFdlIGNvdWxkIHRyeSB0byBwcmVkaWN0IHRpbWUgdW50aWwgdGhlIHRha2VvZmYsIHRoZSBpbnRlbnNpdHkgb2YgdGhlIGdyb3d0aCBhdCB0aGUgdGFrZW9mZiBwb2ludCwgdGhlIHRpbWUgdW50aWwgaXQgcmV0dXJucyB0byB6ZXJvLCB0aGUgYXJlYSB1bmRlciB0aGUgY3VydmUsIG9yIGV2ZXJ5IG5vb2sgYW5kIGNoYW5nZS4KCgpgYGB7ciwgZXZhbD1GfQpsaHNfbG9uZ19tZWRpYW4gJT4lIGdncGxvdChhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWQsIGNvbG9yPXdpa2lkYXRhX2lkKSkgKyBnZW9tX2xpbmUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciwgZXZhbD1GfQpsaHNfbG9uZ19tZWRpYW4gJT4lIGdncGxvdChhZXMoeD1kYXRlX2FzZGF0ZSwgeT1kZWF0aHMsIGNvbG9yPXdpa2lkYXRhX2lkKSkgKyBnZW9tX2xpbmUoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmxoc19sb25nX21lZGlhbiAlPiUgZ2dwbG90KGFlcyh4PWRhdGVfYXNkYXRlLCB5PWRlYXRocywgY29sb3I9d2lraWRhdGFfaWQpKSArIGdlb21fbGluZSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIHNjYWxlX3lfbG9nMTAoKQoKYGBgCmBgYHtyLCBldmFsPUZ9CmxpYnJhcnkodHNpYmJsZSkKbGhzX2xvbmdfbWVkaWFuICU+JSBhcnJhbmdlKHdpa2lkYXRhX2lkLGRhdGVfYXNkYXRlKSAlPiUKICBncm91cF9ieSh3aWtpZGF0YV9pZCkgJT4lCiAgbXV0YXRlKGRlYXRoc19mZD10c2liYmxlOjpkaWZmZXJlbmNlKGRlYXRocykpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKGRlYXRoc19mZD4wKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9ZGVhdGhzX2ZkLCBjb2xvcj13aWtpZGF0YV9pZCkpICsgCiAgZ2VvbV9saW5lKCkgKwogICNzdGF0X3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2UgPSBGKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAjICsgc2NhbGVfeV9sb2cxMCgpCmBgYAoKCgoKYGBge3IsIGV2YWw9Rn0KCmxtMSA8LSBsbShkZWF0aHMgfiAgY29uZmlybWVkLGRhdGE9bGhzX2xvbmdfbWVkaWFuICU+JSBmaWx0ZXIoQ0ZSPDEpKQpsbTIgPC0gbG0oZGVhdGhzIH4gdGVzdGVkX3Blb3BsZSArIGNvbmZpcm1lZCxkYXRhPWxoc19sb25nX21lZGlhbiAlPiUgZmlsdGVyKENGUjwxKSkKCmxpYnJhcnkoZ2dSYW5kb21Gb3Jlc3RzKTsgI2luc3RhbGwucGFja2FnZXMoJ2dnUmFuZG9tRm9yZXN0cycpCnJmMSA8LSByZnNyYyhkZWF0aHN+IGNvbmZpcm1lZCwKICAgICAgICAgICAgICAgICAgICAgIGRhdGE9bGhzX2xvbmdfbWVkaWFuICU+JSBmaWx0ZXIoQ0ZSPDEpICU+JSBhcy5kYXRhLmZyYW1lKCkgKQpnZ19lIDwtIGdnX2Vycm9yKHJmMSkKZ2dfdiA8LSBnZ192YXJpYWJsZShyZjEpCnBsb3QoZ2dfdiwgcGFuZWw9VFJVRSwgc2U9Ljk1LCBzcGFuPTEuMiwgYWxwaGE9LjQpIAoKcmYxIDwtIHJmc3JjKGRlYXRoc34gY29uZmlybWVkICsgdGVzdGVkX3Blb3BsZSwKICAgICAgICAgICAgICAgICAgICAgIGRhdGE9bGhzX2xvbmdfbWVkaWFuICU+JSBmaWx0ZXIoQ0ZSPDEpICU+JSBhcy5kYXRhLmZyYW1lKCkgKQpnZ19lIDwtIGdnX2Vycm9yKHJmMSkKZ2dfdiA8LSBnZ192YXJpYWJsZShyZjEpCnBsb3QoZ2dfdiwgcGFuZWw9VFJVRSwgc2U9Ljk1LCBzcGFuPTEuMiwgYWxwaGE9LjQpCgoKcmYyIDwtIHJmc3JjKENGUiB+ICB0ZXN0ZWRfcGVvcGxlX2xvZywKICAgICAgICAgICAgICAgICAgICAgIGRhdGE9bGhzX2xvbmdfbWVkaWFuICU+JSAKICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShDRlI9ZGVhdGhzL2NvbmZpcm1lZCkgJT4lCiAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUodGVzdGVkX3Blb3BsZV9sb2c9bG9nKHRlc3RlZF9wZW9wbGUrMSkpICU+JQogICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKENGUjwxKSAlPiUgYXMuZGF0YS5mcmFtZSgpCiAgICAgICAgICAgICApCmdnX3YgPC0gZ2dfdmFyaWFibGUocmYyKQpwbG90KGdnX3YsIHBhbmVsPVRSVUUsIHNlPS45NSwgc3Bhbj0xLjIsIGFscGhhPS40KQoKcmYyIDwtIHJmc3JjKENGUiB+ICB0ZXN0ZWRfcGVvcGxlX2xvZyArIGNvbmZpcm1lZF9sb2csCiAgICAgICAgICAgICAgICAgICAgICBkYXRhPWxoc19sb25nX21lZGlhbiAlPiUgCiAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoQ0ZSPWRlYXRocy9jb25maXJtZWQpICU+JQogICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHRlc3RlZF9wZW9wbGVfbG9nPWxvZyh0ZXN0ZWRfcGVvcGxlKzEpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nPWxvZyhjb25maXJtZWQrMSkpICU+JQogICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKENGUjwxKSAlPiUgYXMuZGF0YS5mcmFtZSgpCiAgICAgICAgICAgICApCmdnX3YgPC0gZ2dfdmFyaWFibGUocmYyKQpwbG90KGdnX3YsIHBhbmVsPVRSVUUsIHNlPS45NSwgc3Bhbj0xLjIsIGFscGhhPS40KQoKCiNUaHJvdyBpbiB0aW1lCnJmMyA8LSByZnNyYyhDRlIgfiAgcG9zaXRpdmVfcGVyYyArIHRlc3RlZF9wZW9wbGVfbG9nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWxoc19sb25nX21lZGlhbiAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShDRlI9ZGVhdGhzL2NvbmZpcm1lZCkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShwb3NpdGl2ZV9wZXJjPWNvbmZpcm1lZC90ZXN0ZWRfcGVvcGxlKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHRlc3RlZF9wZW9wbGVfbG9nPWxvZyh0ZXN0ZWRfcGVvcGxlKzEpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9sb2c9bG9nKGNvbmZpcm1lZCsxKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihDRlI8MSkgJT4lIGFzLmRhdGEuZnJhbWUoKQogICAgICAgICAgICAgKQpnZ192IDwtIGdnX3ZhcmlhYmxlKHJmMykKcGxvdChnZ192LCBwYW5lbD1UUlVFLCBzZT0uOTUsIHNwYW49MS4yLCBhbHBoYT0uNCkKCnBhcnRpYWxfQm9zdG9uIDwtIHBsb3QudmFyaWFibGUocmYzLApwYXJ0aWFsPVRSVUUsIHNvcnRlZD1GQUxTRSwKc2hvdy5wbG90cyA9IEZBTFNFICkKCmdnX3AgPC0gZ2dfcGFydGlhbChwYXJ0aWFsX0Jvc3RvbikKcGxvdChnZ19wLCBwYW5lbD1UUlVFLCBwb2ludHMgPSBGICkKCgpjb3BwZXJfY3RzIDwtcXVhbnRpbGVfcHRzKGxoc19sb25nX21lZGlhbiR0ZXN0ZWRfcGVvcGxlX2xvZywgZ3JvdXBzID0gNiwgaW50ZXJ2YWxzID0gVFJVRSkKcGFydGlhbF9jb3Bsb3RfQm9zdG9uIDwtIGdnX3BhcnRpYWxfY29wbG90KHJmMiwgeHZhcj0iY29uZmlybWVkX2xvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBzPXJtX2dycCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93LnBsb3RzPUZBTFNFKQoKCgpzdW1tYXJ5KGxoc19sb25nX21lZGlhbiRDRlIpCgpsaHNfbG9uZ19tZWRpYW4gJT4lIGZpbHRlcihjb25maXJtZWQ+MTApICU+JSBmaWx0ZXIoQ0ZSPDEpICU+JSBwdWxsKENGUikgJT4lIHN1bW1hcnkoKSAjMC4wMjk3Mjk3ICB0aGF0J3MgYSBtZWRpYW4gQ0ZSIG9mIGFib3V0IDMlCmxoc19sb25nX21lZGlhbiAlPiUgZmlsdGVyKGNvbmZpcm1lZD4xMCkgJT4lIGZpbHRlcihDRlI8MSkgJT4lIHB1bGwoQ0ZSKSAlPiUgaGlzdChicmVha3M9NTApCgpsaHNfbG9uZ19tZWRpYW4gJT4lIGZpbHRlcihjb25maXJtZWQ+MTApICU+JSBmaWx0ZXIoQ0ZSPDEpICU+JSBnZ3Bsb3QoYWVzKHg9Q0ZSKSkgKyBnZW9tX2RlbnNpdHkoKQoKCmBgYAoKCgpgYGB7ciwgZXZhbD1GfQojVGhpcyBjb2RlIGlzIG5vdyBkZXByaWNhdGVkIGluIGZhdm9yIG9mIHRoZSB0cmVlIGJhc2UgbWV0aG9kIGFib3ZlCgpwbGFjZXMgPC0gbGhzX2xvbmdfY2xlYW4kd2lraWRhdGFfaWQgJT4lIHVuaXF1ZSgpICU+JSBuYS5vbWl0KCkgOyBsZW5ndGgocGxhY2VzKQpkYXRhc2V0cyA8LSBsaHNfbG9uZ19jbGVhbiRkYXRhc2V0ICU+JSB1bmlxdWUoKSAlPiUgbmEub21pdCgpIDsgdGFibGUoZGF0YXNldCkKCnRlbXBfbGlzdCA8LSBsaXN0KCkKZm9yKHAgaW4gcGxhY2VzKXsKICAgIHByaW50KHApCiAgICBmb3IoZCBpbiBkYXRhc2V0cyl7CiAgICAgIHRlbXAgPC0gTlVMTAogICAgICB0ZW1wIDwtIGxoc19sb25nX2NsZWFuICU+JSAKICAgICAgICAgICAgICBhcnJhbmdlKGRhdGVfYXNkYXRlKSAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKGRhdGFzZXQgJWluJSBkKSAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKHdpa2lkYXRhX2lkICVpbiUgcCkgJT4lIAogICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nPWxvZyhjb25maXJtZWQrMSkpICU+JQogICAgICAgICAgICAgIG11dGF0ZShkZWF0aHNfbG9nPWxvZyhkZWF0aHMrMSkpICU+JQogICAgICAgICAgICAgIG11dGF0ZSh0ZXN0ZWRfcGVvcGxlX2xvZz1sb2codGVzdGVkX3Blb3BsZSsxKSkgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKHQ9IGFzLm51bWVyaWMoZGF0ZV9hc2RhdGUpIC0gbWluKGFzLm51bWVyaWMoZGF0ZV9hc2RhdGUpKSArMSAgKSAlPiUgI3N0YXJ0IGF0IDEgdG8gbWFrZSBpbmRleGluZyBlYXNpZXIKICAgICAgICAgICAgICBtdXRhdGUoaT0gcm93X251bWJlcigpICApICMgYWN0dWFsbHkgbmVlZCB0aGlzCiAgICAgICAgCiAgICAgIGlfb3JpZ2luYWwgPC0gdGVtcCRpCiAgICAgIAogICAgICBpZiggbnJvdyh0ZW1wKT09MCApIHsgbmV4dH0gI3ByaW50KCJlcnJvciIpOwogICAgICBwcmludChwKQogICAgICAKICAgICAgI2JwIDwtIGJyZWFrcG9pbnRzKGNvbmZpcm1lZF9sb2cgfiAxLCBkYXRhPXRlbXApCiAgICAgIGJwIDwtIE5VTEwKICAgICAgbG0xIDwtIE5VTEwKICAgICAgeV9oYXQgPC0gTkEKICAgICAgY2RmIDwtIE5VTEwKICAgICAgdHJ5KHsKICAgICAgICAgICAgI2lmIGl0IGZhaWxzIGZhbGwgYmFjayB0byBqdXN0IGEgbG0KICAgICAgICBsbTEgPC0gbG0oY29uZmlybWVkX2xvZyB+IDEgKyB0LCBkYXRhPXRlbXApCiAgICAKICAgICAgICBjZGYgPC0gZGF0YS5mcmFtZSgKICAgICAgICAgICAgICAgICAgICAgICAgICB0PSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maXJtZWRfbG9nX2ludGVyY2VwdD0gY29lZihsbTEpWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpcm1lZF9sb2dfc2xvcGU9IGNvZWYobG0xKVsyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maXJtZWRfbG9nX3Nsb3BlX2JyZWFrPTAKICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgY29uZmlybWVkX2xvZ195X2hhdD1maXR0ZWQudmFsdWVzKGxtMSkKICAgICAgfSkKICAgICAgCiAgICAgIHRyeSh7CiAgICAgICAgYnAgPC0gYnJlYWtwb2ludHMoY29uZmlybWVkX2xvZyB+IDEgKyB0LCBkYXRhPXRlbXAsIGg9MykKICAgICAgICAKICAgICAgICBjZGYgPC0gZGF0YS5mcmFtZSgKICAgICAgICAgICAgICAgICAgICAgICAgICBpPSBjKDEsYnAkYnJlYWtwb2ludHMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maXJtZWRfbG9nX2ludGVyY2VwdD0gY29lZihicClbLDFdLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpcm1lZF9sb2dfc2xvcGU9IGNvZWYoYnApWywyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maXJtZWRfbG9nX3Nsb3BlX2JyZWFrPTEKICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgY29uZmlybWVkX2xvZ195X2hhdD1maXR0ZWQudmFsdWVzKGJwKQogICAgICB9KQogICAgICAKICAgICAgdHJ5KHsKICAgICAgICB0ZW1wMiA8LSB0ZW1wCiAgICAgICAgdGVtcDIkY29uZmlybWVkX2xvZ195X2hhdCA8LSBOQQogICAgICAgIHRlbXAyJGNvbmZpcm1lZF9sb2dfeV9oYXQgPC0gY29uZmlybWVkX2xvZ195X2hhdAogICAgICAgIAogICAgICAgIHRlbXAyIDwtIHRlbXAyICU+JSAKICAgICAgICAgICAgICAgIGxlZnRfam9pbihjZGYpIAogICAgICAgIHE9cGFzdGUwKHAsIl8iLGQpCiAgICAgICAgdGVtcDIgPC0gdGVtcDIgJT4lIAogICAgICAgICAgICAgICAgICBleHBhbmQoZGF0YXNldCwgZ2lkLGdlb25hbWVpZCwgd2lraWRhdGFfaWQsdD1taW4odGVtcCR0KTptYXgodGVtcCR0KSkgJT4lICNleHBhbmQgdGhpcyB0byBpbmNsdWRlIGFsbCB0aGUgdCAKICAgICAgICAgICAgICAgICAgbGVmdF9qb2luKHRlbXAyKSAlPiUgCiAgICAgICAgICAgICAgICAgIG11dGF0ZShkYXRlX2FzZGF0ZT1taW4oZGF0ZV9hc2RhdGUsIG5hLnJtPVQpLTErdCkgJT4lICNnbyBiYWNrIGludGVycCBkYXRlIGFnYWluCiAgICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nX3Nsb3BlX2JyZWFrID0gY29uZmlybWVkX2xvZ19zbG9wZV9icmVhayAlPiUgcmVwbGFjZV9uYSgwKSAlPiUgY3Vtc3VtKCkgKSAlPiUKICAgICAgICAgICAgICAgICAgZmlsbChjb25maXJtZWRfbG9nX2ludGVyY2VwdCkgJT4lCiAgICAgICAgICAgICAgICAgIGZpbGwoY29uZmlybWVkX2xvZ19zbG9wZSkgJT4lCiAgICAgICAgICAgICAgICAgIG11dGF0ZShjb25maXJtZWRfbG9nX3lfaGF0PSBjb25maXJtZWRfbG9nX2ludGVyY2VwdCArIGNvbmZpcm1lZF9sb2dfc2xvcGUqdCApICU+JSAKICAgICAgICAgICAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9sb2dfc2xvcGVfcGVyY2VudF9jaGFuZ2UgPSByb3VuZCgoZXhwKGNvbmZpcm1lZF9sb2dfc2xvcGUpLTEpKjEwMCwyKSkgCgogICAgICAgIHRlbXBfbGlzdFtbYXMuY2hhcmFjdGVyKHEpXV0gPC0gdGVtcDIKICAgICAgfSkKICAgICAgI2lmKCBpcy5uYSggdGVtcF9saXN0W1thcy5jaGFyYWN0ZXIocSldXSR5X2hhdCkgKSB7cHJpbnQoImVycm9yIik7IGJyZWFrfQogICAgfQp9CiMiMTMwNTUiCnRlbXBfZGYgPC0gYmluZF9yb3dzKHRlbXBfbGlzdCkKZGltKHRlbXBfZGYpICNiaWdnZXIgYmVjYXVzZSB3ZSdyZSBpbnRlcnBvbGF0aW5nIG5vdwoKIyBpbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpCiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInRpZHl2ZXJzZS9tdWx0aWRwbHlyIikKCmxpYnJhcnkobXVsdGlkcGx5cikKbGlicmFyeShkcGx5ciwgd2Fybi5jb25mbGljdHMgPSBGQUxTRSkKI2NsdXN0ZXIgPC0gbmV3X2NsdXN0ZXIoNCkKCiNuZWVkIHRvIHN1cHJlc3MgbWVzc2FnZXMKcmV4X2Z1bmN0aW9uIDwtIGZ1bmN0aW9uKHgpewogIHRlbXA9ZGF0YS5mcmFtZShjb25maXJtZWRfbG9nX3Nsb3BlPXgpCiAgdHJ5Q2F0Y2goewogICAgI2lmIHRoZXJlJ3MgYW4gTkEgaW4geCB3ZSBnZXQgYW4gZXJyb3IgYmVjYXVzZSBicmVha3BvaW50cyBpcyBvbmUgc2hvcnQKICAgIHByZWRpY3Rpb24gPC0gYnJlYWtwb2ludHMoZm9ybXVsYT1jb25maXJtZWRfbG9nX3Nsb3BlIH4gMSwgZGF0YT10ZW1wLCBoPTMpICU+JSBmaXR0ZWQudmFsdWVzKCkKICAgIHJlc3VsdD1yZXAoTkEsIGxlbmd0aCh4KSApCiAgICByZXN1bHRbIWlzLm5hKHgpXSA8LXByZWRpY3Rpb24KICAgIHJldHVybihyZXN1bHQpCiAgICAKICB9LCBlcnJvcj1mdW5jdGlvbihlKXt9KQogIAogIHJldHVybiggcmVwKE5BLCBsZW5ndGgoeCkgKSApCiAgICAgICAgIAp9CiNkaWRuJ3QgdGFrZSB0b28gbG9uZyBub3cKCiNsaWJyYXJ5KG11bHRpZHBseXIpCiNsaWJyYXJ5KGRwbHlyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFKQojY2x1c3RlciA8LSBuZXdfY2x1c3Rlcig0KQoKbGlicmFyeSh0aWN0b2MpCnRpYygpCmxpYnJhcnkoc3RydWNjaGFuZ2UpCnRlc3QgPC0gdGVtcF9kZiAlPiUgaGVhZCgyMDAwMCkKdGVzdDMgPC0gdGVzdCAlPiUgCiAgICAgICAgICAgICAgICBncm91cF9ieSh3aWtpZGF0YV9pZCkgJT4lIAogICAgICAgICAgICAgICAgI3BhcnRpdGlvbihjbHVzdGVyKSAlPiUKICAgICAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgICAgICAgI211dGF0ZSggY29uZmlybWVkX2xvZ19zbG9wZV95X2hhdCA9IGJyZWFrcG9pbnRzKGZvcm11bGE9Y29uZmlybWVkX2xvZ19zbG9wZSB+IDEsIGRhdGE9LiApICU+JSBmaXR0ZWQudmFsdWVzKCkgKSAlPiUgCiAgICAgICAgICAgICAgICBtdXRhdGUoIGNvbmZpcm1lZF9sb2dfc2xvcGVfeV9oYXQgPSByZXhfZnVuY3Rpb24oY29uZmlybWVkX2xvZ19zbG9wZSkgKSAlPiUgICNmYWlscyBvbiB0aGUgY2x1c3RlcgogICAgICAgICAgICAgICAgdW5ncm91cCgpICMlPiUKICAgICAgICAgICAgICAgICNjb2xsZWN0KCkKdG9jKCkgIzQ4IHNlY29uZHMgZm9yIDEwayAjMTIyIHNlY29uZHMgZm9yIDIwawoKc2F2ZVJEUyh0ZW1wX2RmLCAiL21lZGlhL3NreW5ldDIvOTA1ODg0ZjAtNzU0Ni00MjczLTkwNjEtMTJhNzkwODMwYmViL3J3ZF9naXRodWJfcHJpdmF0ZS9ORVNTY292aWQxOS9kYXRhX3RlbXAvbGhzX2xvbmdfaW50ZXJwb2xhdGVkLlJkcyIpCgpgYGAKCgoKCgoKCgoKYGBge3IsIGV2YWw9RiwgZWNobz1GLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxlcnJvcj1GQUxTRX0KCiNIZXJlIGlzIHdoZXJlIEkgd29ya2VkIG91dCB0aGUgaWRlYSBvZiBmaXR0aW5nIHBpZWNld2lzZSBsaW5lYXIgZnVuY3Rpb25zIHRvIGVhY2ggZGF0YXNldCBpbmRlcGVuZGVudGx5LiBJdCdzIG5vdyByZXBsYWNlZCB3aXRoIGEgZnVsbHkgYXV0b21hdGVkIHBpcGxpbmUgYmFzZWQgb24gdHJlZXMuCgpjb3VudF9kYXRhc2V0cyA8LSBsaHNfbG9uZ19jbGVhbiAlPiUgZHBseXI6OnNlbGVjdCh3aWtpZGF0YV9pZCwgZGF0YXNldCkgJT4lIGRpc3RpbmN0KCkgJT4lIGNvdW50KHdpa2lkYXRhX2lkKQoKZm9ybXVsYSA9IGNvbmZpcm1lZF9sb2cgfiAxICsgZGF0ZV9yYW5rICMrIEkoZGF0ZV9yYW5rXjIpICsgSShkYXRlX3JhbmteMykKaD01CiNiZXhhciBjb3VudHkKbGlicmFyeShzdHJ1Y2NoYW5nZSkgOyAjaW5zdGFsbC5wYWNrYWdlcygnc3RydWNjaGFuZ2UnKQp0ZW1wIDwtIGxoc19sb25nX2NsZWFuICU+JSBhcnJhbmdlKGRhdGVfYXNkYXRlKSAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkICVpbiUgIlExNjg2MSIpICU+JSAgbXV0YXRlKGNvbmZpcm1lZF9sb2c9bG9nKGNvbmZpcm1lZCsxKSkgJT4lCiAgICAgICAgbXV0YXRlKGRhdGVfcmFuaz0gYXMubnVtZXJpYyhkYXRlX2FzZGF0ZSkgLSBtaW4oYXMubnVtZXJpYyhkYXRlX2FzZGF0ZSkpKSAgCgp0YWJsZSh0ZW1wJGRhdGFzZXQpCgp0ZW1wX3VzYWZhY3RzIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0idXNhZmFjdHMiKQpicF91c2FmYWN0cyA8LSBicmVha3BvaW50cyhmb3JtdWxhLCBkYXRhPXRlbXBfdXNhZmFjdHMsaD1oKQp0ZW1wX3VzYWZhY3RzJHlfaGF0IDwtIGZpdHRlZC52YWx1ZXMoYnBfdXNhZmFjdHMpCnRlbXBfdXNhZmFjdHMkZ3JvdXBzIDwtIDA7IHRlbXBfdXNhZmFjdHMkZ3JvdXBzW2JwX3VzYWZhY3RzJGJyZWFrcG9pbnRzKzFdIDwtIDEgOyB0ZW1wX3VzYWZhY3RzJGdyb3VwcyA8LSBjdW1zdW0odGVtcF91c2FmYWN0cyRncm91cHMpKzEKCnRlbXBfbnl0IDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0ibnl0IikKYnBfbnl0IDwtIGJyZWFrcG9pbnRzKGZvcm11bGEsIGRhdGE9dGVtcF9ueXQsaD1oKQp0ZW1wX255dCR5X2hhdCA8LSBmaXR0ZWQudmFsdWVzKGJwX255dCkKdGVtcF9ueXQkZ3JvdXBzIDwtIDA7IHRlbXBfbnl0JGdyb3Vwc1ticF9ueXQkYnJlYWtwb2ludHMrMV0gPC0gMSA7IHRlbXBfbnl0JGdyb3VwcyA8LSBjdW1zdW0odGVtcF9ueXQkZ3JvdXBzKSsxCgoKdGVtcF9DU1NFIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iQ1NTRSIpCmJwX0NTU0UgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX0NTU0UsaD1oKQp0ZW1wX0NTU0UkeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF9DU1NFKQp0ZW1wX0NTU0UkZ3JvdXBzIDwtIDA7IHRlbXBfQ1NTRSRncm91cHNbYnBfQ1NTRSRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF9DU1NFJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9DU1NFJGdyb3VwcykrMQoKdGVtcF9iaW5nIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iYmluZyIpCmJwX2JpbmcgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX2JpbmcsaD1oKSAjdGhpcyBmYWlscyBiYyB0b28gZmV3CmxtX2JpbmcgPC1sbShmb3JtdWxhLCBkYXRhPXRlbXBfYmluZykKdGVtcF9iaW5nJHlfaGF0IDwtIGZpdHRlZC52YWx1ZXMobG1fYmluZykKdGVtcF9iaW5nJGdyb3VwcyA8LTEKCnRlbXBfZGYgPC0gYmluZF9yb3dzKHRlbXBfbnl0LCB0ZW1wX0NTU0UsIHRlbXBfYmluZywgdGVtcF91c2FmYWN0cykgICU+JSAKICAgICAgICAgICAgYXJyYW5nZShkYXRhc2V0LGRhdGVfYXNkYXRlKSAlPiUgCiAgICAgICAgICAgbXV0YXRlKGdyb3Vwcz1wYXN0ZShkYXRhc2V0LGdyb3VwcykpCgp0ZW1wX2RmMiA8LSBiaW5kX3Jvd3ModGVtcF9ueXQsIHRlbXBfQ1NTRSwgdGVtcF9iaW5nLCB0ZW1wX3VzYWZhY3RzKSAlPiUgCiAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICU+JSAKICAgICAgICAgICAgZ3JvdXBfYnkoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgICAgIHN1bW1hcmlzZSh5X2hhdF9tZWFuPW1lYW4oeV9oYXQsIG5hLnJtPVQpKSAlPiUKICAgICAgICAgICAgbXV0YXRlKGdyb3Vwcz05OSkKCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoZGF0YT10ZW1wX2RmLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSkgKwogICBnZW9tX2xpbmUoZGF0YT10ZW1wX2RmLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXBzKSkgKwogICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJCZXhhciBDb3VudHkgKFExNjg2MSkgQ29uZmlybWVkIikKCgoKIyMjIyMKI0NoaW5hIFExNDgKdGVtcCA8LSBsaHNfbG9uZ19jbGVhbiAlPiUgYXJyYW5nZShkYXRlX2FzZGF0ZSkgJT4lIAogICAgICAgIGZpbHRlcih3aWtpZGF0YV9pZCAlaW4lICJRMTQ4IikgJT4lIAogICAgICAgIGdyb3VwX2J5KGRhdGFzZXQsIGRhdGVfYXNkYXRlKSAlPiUKICAgICAgICAgIHN1bW1hcmlzZShjb25maXJtZWQ9bWF4KGNvbmZpcm1lZCwgbmEucm09VCkgKSAlPiUgI3RoaXMgaXMgYSBwcm9ibGVtIGR1cGVzIHdpdGggdGhlIHNhbWUgZGF0ZSAgI3RoaXMgZml4ZXMgYSBsb3Qgb2YgdGhpbmdzIGJ1dCB3ZSBuZWVkIHRvIGZpZ3VyZSBvdXQgdGhlIG9yaWdpbiBvZiB0aGlzIHByb2JsZW0KICAgICAgICB1bmdyb3VwKCkgJT4lCiAgICAgICAgbXV0YXRlKGNvbmZpcm1lZF9sb2c9bG9nKGNvbmZpcm1lZCsxKSkgJT4lIAogICAgICAgIG11dGF0ZShkYXRlX3Jhbms9IGFzLm51bWVyaWMoZGF0ZV9hc2RhdGUpIC0gbWluKGFzLm51bWVyaWMoZGF0ZV9hc2RhdGUpKSkgIAoKCnRlbXBfd2lraXBlZGlhIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0id2lraXBlZGlhIikKYnBfd2lraXBlZGlhIDwtIGJyZWFrcG9pbnRzKGZvcm11bGEsIGRhdGE9dGVtcF93aWtpcGVkaWEsaD1oKQp0ZW1wX3dpa2lwZWRpYSR5X2hhdCA8LSBmaXR0ZWQudmFsdWVzKGJwX3dpa2lwZWRpYSkKdGVtcF93aWtpcGVkaWEkZ3JvdXBzIDwtIDA7IHRlbXBfd2lraXBlZGlhJGdyb3Vwc1ticF93aWtpcGVkaWEkYnJlYWtwb2ludHMrMV0gPC0gMSA7IHRlbXBfd2lraXBlZGlhJGdyb3VwcyA8LSBjdW1zdW0odGVtcF93aWtpcGVkaWEkZ3JvdXBzKSsxCgoKdGVtcF9lY2RjIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iZWNkYyIpCmJwX2VjZGMgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX2VjZGMsaD1oKQp0ZW1wX2VjZGMkeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF9lY2RjKQp0ZW1wX2VjZGMkZ3JvdXBzIDwtIDA7IHRlbXBfZWNkYyRncm91cHNbYnBfZWNkYyRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF9lY2RjJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9lY2RjJGdyb3VwcykrMQoKdGVtcF93aG8gPC0gdGVtcCAlPiUgZmlsdGVyKGRhdGFzZXQ9PSJ3aG8iKQpicF93aG8gPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX3dobyxoPWgpCnRlbXBfd2hvJHlfaGF0IDwtIGZpdHRlZC52YWx1ZXMoYnBfd2hvKQp0ZW1wX3dobyRncm91cHMgPC0gMDsgdGVtcF93aG8kZ3JvdXBzW2JwX3dobyRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF93aG8kZ3JvdXBzIDwtIGN1bXN1bSh0ZW1wX3dobyRncm91cHMpKzEKCgp0ZW1wX21ldGFiaW90YSA8LSB0ZW1wICU+JSBmaWx0ZXIoZGF0YXNldD09Im1ldGFiaW90YSIpCmJwX21ldGFiaW90YSA8LSBicmVha3BvaW50cyhmb3JtdWxhLCBkYXRhPXRlbXBfbWV0YWJpb3RhLGg9aCkKdGVtcF9tZXRhYmlvdGEkeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF9tZXRhYmlvdGEpCnRlbXBfbWV0YWJpb3RhJGdyb3VwcyA8LSAwOyB0ZW1wX21ldGFiaW90YSRncm91cHNbYnBfbWV0YWJpb3RhJGJyZWFrcG9pbnRzKzFdIDwtIDEgOyB0ZW1wX21ldGFiaW90YSRncm91cHMgPC0gY3Vtc3VtKHRlbXBfbWV0YWJpb3RhJGdyb3VwcykrMQoKdGVtcF9iaW5nIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iYmluZyIpCmJwX2JpbmcgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX2JpbmcsaD1oKSAjdGhpcyBmYWlscyBiYyB0b28gZmV3CmxtX2JpbmcgPC1sbShmb3JtdWxhLCBkYXRhPXRlbXBfYmluZykKdGVtcF9iaW5nJHlfaGF0IDwtIGZpdHRlZC52YWx1ZXMobG1fYmluZykKdGVtcF9iaW5nJGdyb3VwcyA8LTEKCnRlbXBfZGYgPC0gYmluZF9yb3dzKHRlbXBfZWNkYywgdGVtcF9tZXRhYmlvdGEsIHRlbXBfYmluZywgdGVtcF93aG8sIHRlbXBfd2lraXBlZGlhKSAlPiUgCiAgICAgICAgICAgIGFycmFuZ2UoZGF0YXNldCxkYXRlX2FzZGF0ZSkgJT4lIAogICAgICAgICAgIG11dGF0ZShncm91cHM9cGFzdGUoZGF0YXNldCxncm91cHMpKQoKdGVtcF9kZjIgPC0gYmluZF9yb3dzKHRlbXBfZWNkYywgdGVtcF9tZXRhYmlvdGEsIHRlbXBfYmluZywgdGVtcF93aG8sIHRlbXBfd2lraXBlZGlhKSAlPiUgCiAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICU+JSAKICAgICAgICAgICAgZ3JvdXBfYnkoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgICAgIHN1bW1hcmlzZSh5X2hhdF9tZWFuPW1lYW4oeV9oYXQsIG5hLnJtPVQpKSAlPiUKICAgICAgICAgICAgbXV0YXRlKGdyb3Vwcz05OSkKCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoZGF0YT10ZW1wX2RmLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSkgKwogICBnZW9tX2xpbmUoZGF0YT10ZW1wX2RmLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXBzKSkgKwogICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJDaGluYSAoUTE0OCkgQ29uZmlybWVkIikKICAgI2dlb21fdmxpbmUoeGludGVyY2VwdD1icCRicmVha3BvaW50cykKCgojSW5kaWEKIyJRNjY4Igp0ZW1wIDwtIGxoc19sb25nX2NsZWFuICU+JSBhcnJhbmdlKGRhdGVfYXNkYXRlKSAlPiUgCiAgICAgICAgZmlsdGVyKHdpa2lkYXRhX2lkICVpbiUgIlE2NjgiKSAlPiUgCiAgICAgICAgZ3JvdXBfYnkoZGF0YXNldCwgZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgc3VtbWFyaXNlKGNvbmZpcm1lZD1tYXgoY29uZmlybWVkLCBuYS5ybT1UKSApICU+JSAjdGhpcyBpcyBhIHByb2JsZW0gZHVwZXMgd2l0aCB0aGUgc2FtZSBkYXRlICAjdGhpcyBmaXhlcyBhIGxvdCBvZiB0aGluZ3MgYnV0IHdlIG5lZWQgdG8gZmlndXJlIG91dCB0aGUgb3JpZ2luIG9mIHRoaXMgcHJvYmxlbQogICAgICAgIHVuZ3JvdXAoKSAlPiUKICAgICAgICBtdXRhdGUoY29uZmlybWVkX2xvZz1sb2coY29uZmlybWVkKzEpKSAlPiUgCiAgICAgICAgbXV0YXRlKGRhdGVfcmFuaz0gYXMubnVtZXJpYyhkYXRlX2FzZGF0ZSkgLSBtaW4oYXMubnVtZXJpYyhkYXRlX2FzZGF0ZSkpKSAgCnRhYmxlKHRlbXAkZGF0YXNldCkKCnRlbXBfY292aWQxOWluZGlhIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iY292aWQxOWluZGlhIikKYnBfY292aWQxOWluZGlhIDwtIGJyZWFrcG9pbnRzKGZvcm11bGEsIGRhdGE9dGVtcF9jb3ZpZDE5aW5kaWEsaD1oKQp0ZW1wX2NvdmlkMTlpbmRpYSR5X2hhdCA8LSBmaXR0ZWQudmFsdWVzKGJwX2NvdmlkMTlpbmRpYSkKdGVtcF9jb3ZpZDE5aW5kaWEkZ3JvdXBzIDwtIDA7IHRlbXBfY292aWQxOWluZGlhJGdyb3Vwc1ticF9jb3ZpZDE5aW5kaWEkYnJlYWtwb2ludHMrMV0gPC0gMSA7IHRlbXBfY292aWQxOWluZGlhJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9jb3ZpZDE5aW5kaWEkZ3JvdXBzKSsxCgp0ZW1wX3dpa2lwZWRpYSA8LSB0ZW1wICU+JSBmaWx0ZXIoZGF0YXNldD09Indpa2lwZWRpYSIpCmJwX3dpa2lwZWRpYSA8LSBicmVha3BvaW50cyhmb3JtdWxhLCBkYXRhPXRlbXBfd2lraXBlZGlhLGg9aCkKdGVtcF93aWtpcGVkaWEkeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF93aWtpcGVkaWEpCnRlbXBfd2lraXBlZGlhJGdyb3VwcyA8LSAwOyB0ZW1wX3dpa2lwZWRpYSRncm91cHNbYnBfd2lraXBlZGlhJGJyZWFrcG9pbnRzKzFdIDwtIDEgOyB0ZW1wX3dpa2lwZWRpYSRncm91cHMgPC0gY3Vtc3VtKHRlbXBfd2lraXBlZGlhJGdyb3VwcykrMQoKdGVtcF9DU1NFIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iQ1NTRSIpCmJwX0NTU0UgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX0NTU0UsaD1oKQp0ZW1wX0NTU0UkeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF9DU1NFKQp0ZW1wX0NTU0UkZ3JvdXBzIDwtIDA7IHRlbXBfQ1NTRSRncm91cHNbYnBfQ1NTRSRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF9DU1NFJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9DU1NFJGdyb3VwcykrMQoKdGVtcF9lY2RjIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iZWNkYyIpCmJwX2VjZGMgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX2VjZGMsaD1oKQp0ZW1wX2VjZGMkeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF9lY2RjKQp0ZW1wX2VjZGMkZ3JvdXBzIDwtIDA7IHRlbXBfZWNkYyRncm91cHNbYnBfZWNkYyRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF9lY2RjJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9lY2RjJGdyb3VwcykrMQoKdGVtcF93aG8gPC0gdGVtcCAlPiUgZmlsdGVyKGRhdGFzZXQ9PSJ3aG8iKQpicF93aG8gPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX3dobyxoPWgpCnRlbXBfd2hvJHlfaGF0IDwtIGZpdHRlZC52YWx1ZXMoYnBfd2hvKQp0ZW1wX3dobyRncm91cHMgPC0gMDsgdGVtcF93aG8kZ3JvdXBzW2JwX3dobyRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF93aG8kZ3JvdXBzIDwtIGN1bXN1bSh0ZW1wX3dobyRncm91cHMpKzEKCnRlbXBfbWV0YWJpb3RhIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0ibWV0YWJpb3RhIikKYnBfbWV0YWJpb3RhIDwtIGJyZWFrcG9pbnRzKGZvcm11bGEsIGRhdGE9dGVtcF9tZXRhYmlvdGEsaD1oKQp0ZW1wX21ldGFiaW90YSR5X2hhdCA8LSBmaXR0ZWQudmFsdWVzKGJwX21ldGFiaW90YSkKdGVtcF9tZXRhYmlvdGEkZ3JvdXBzIDwtIDA7IHRlbXBfbWV0YWJpb3RhJGdyb3Vwc1ticF9tZXRhYmlvdGEkYnJlYWtwb2ludHMrMV0gPC0gMSA7IHRlbXBfbWV0YWJpb3RhJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9tZXRhYmlvdGEkZ3JvdXBzKSsxCgp0ZW1wX2JpbmcgPC0gdGVtcCAlPiUgZmlsdGVyKGRhdGFzZXQ9PSJiaW5nIikKYnBfYmluZyA8LSBicmVha3BvaW50cyhmb3JtdWxhLCBkYXRhPXRlbXBfYmluZyxoPWgpICN0aGlzIGZhaWxzIGJjIHRvbyBmZXcKbG1fYmluZyA8LWxtKGZvcm11bGEsIGRhdGE9dGVtcF9iaW5nKQp0ZW1wX2JpbmckeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhsbV9iaW5nKQp0ZW1wX2JpbmckZ3JvdXBzIDwtMQoKdGVtcF9kZiA8LSBiaW5kX3Jvd3ModGVtcF9jb3ZpZDE5aW5kaWEsIHRlbXBfd2lraXBlZGlhLCB0ZW1wX0NTU0UsIHRlbXBfZWNkYywgdGVtcF93aG8sIHRlbXBfbWV0YWJpb3RhLCB0ZW1wX2JpbmcpICU+JSAKICAgICAgICAgICAgYXJyYW5nZShkYXRhc2V0LGRhdGVfYXNkYXRlKSAlPiUgCiAgICAgICAgICAgbXV0YXRlKGdyb3Vwcz1wYXN0ZShkYXRhc2V0LGdyb3VwcykpCgp0ZW1wX2RmMiA8LSBiaW5kX3Jvd3ModGVtcF9jb3ZpZDE5aW5kaWEsIHRlbXBfd2lraXBlZGlhLCB0ZW1wX0NTU0UsIHRlbXBfZWNkYywgdGVtcF93aG8sIHRlbXBfbWV0YWJpb3RhLCB0ZW1wX2JpbmcpICU+JSAKICAgICAgICAgICAgYXJyYW5nZShkYXRlX2FzZGF0ZSkgJT4lIAogICAgICAgICAgICBncm91cF9ieShkYXRlX2FzZGF0ZSkgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXNlKHlfaGF0X21lYW49bWVhbih5X2hhdCwgbmEucm09VCkpICU+JQogICAgICAgICAgICBtdXRhdGUoZ3JvdXBzPTk5KQoKZ2dwbG90KCkgKyAKICAgZ2VvbV9wb2ludChkYXRhPXRlbXBfZGYsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PWNvbmZpcm1lZF9sb2csIGNvbG9yPWRhdGFzZXQpLCBhbHBoYT0uMykgKwogICBnZW9tX2xpbmUoZGF0YT10ZW1wX2RmLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdCwgY29sb3I9ZGF0YXNldCwgZ3JvdXA9Z3JvdXBzKSkgKwogICAjZ2VvbV9saW5lKGRhdGE9dGVtcF9kZjIsIGFlcyh4PWRhdGVfYXNkYXRlLCB5PXlfaGF0X21lYW4pLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgIHRoZW1lX2J3KCkgKwogICBnZ3RpdGxlKCJJbmRpYSAoUTY2OCkgQ29uZmlybWVkIikKCgojRmxvcmlkYQojUTgxMgp0ZW1wIDwtIGxoc19sb25nX2NsZWFuICU+JSBhcnJhbmdlKGRhdGVfYXNkYXRlKSAlPiUgCiAgICAgICAgZmlsdGVyKHdpa2lkYXRhX2lkICVpbiUgIlE4MTIiKSAlPiUgCiAgICAgICAgZ3JvdXBfYnkoZGF0YXNldCwgZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgc3VtbWFyaXNlKGNvbmZpcm1lZD1tYXgoY29uZmlybWVkLCBuYS5ybT1UKSApICU+JSAjdGhpcyBpcyBhIHByb2JsZW0gZHVwZXMgd2l0aCB0aGUgc2FtZSBkYXRlICAjdGhpcyBmaXhlcyBhIGxvdCBvZiB0aGluZ3MgYnV0IHdlIG5lZWQgdG8gZmlndXJlIG91dCB0aGUgb3JpZ2luIG9mIHRoaXMgcHJvYmxlbQogICAgICAgIHVuZ3JvdXAoKSAlPiUKICAgICAgICBtdXRhdGUoY29uZmlybWVkX2xvZz1sb2coY29uZmlybWVkKzEpKSAlPiUKICAgICAgICBtdXRhdGUoZGF0ZV9yYW5rPSBhcy5udW1lcmljKGRhdGVfYXNkYXRlKSAtIG1pbihhcy5udW1lcmljKGRhdGVfYXNkYXRlKSkpICAKdGFibGUodGVtcCRkYXRhc2V0KQoKdGVtcF9jb3ZpZHRyYWNraW5nIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0iY292aWR0cmFja2luZyIpCmJwX2NvdmlkdHJhY2tpbmcgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX2NvdmlkdHJhY2tpbmcsaD1oKQp0ZW1wX2NvdmlkdHJhY2tpbmckeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhicF9jb3ZpZHRyYWNraW5nKQp0ZW1wX2NvdmlkdHJhY2tpbmckZ3JvdXBzIDwtIDA7IHRlbXBfY292aWR0cmFja2luZyRncm91cHNbYnBfY292aWR0cmFja2luZyRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF9jb3ZpZHRyYWNraW5nJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9jb3ZpZHRyYWNraW5nJGdyb3VwcykrMQoKdGVtcF93aWtpcGVkaWEgPC0gdGVtcCAlPiUgZmlsdGVyKGRhdGFzZXQ9PSJ3aWtpcGVkaWEiKQpicF93aWtpcGVkaWEgPC0gYnJlYWtwb2ludHMoZm9ybXVsYSwgZGF0YT10ZW1wX3dpa2lwZWRpYSxoPWgpCnRlbXBfd2lraXBlZGlhJHlfaGF0IDwtIGZpdHRlZC52YWx1ZXMoYnBfd2lraXBlZGlhKQp0ZW1wX3dpa2lwZWRpYSRncm91cHMgPC0gMDsgdGVtcF93aWtpcGVkaWEkZ3JvdXBzW2JwX3dpa2lwZWRpYSRicmVha3BvaW50cysxXSA8LSAxIDsgdGVtcF93aWtpcGVkaWEkZ3JvdXBzIDwtIGN1bXN1bSh0ZW1wX3dpa2lwZWRpYSRncm91cHMpKzEKCnRlbXBfbWV0YWJpb3RhIDwtIHRlbXAgJT4lIGZpbHRlcihkYXRhc2V0PT0ibWV0YWJpb3RhIikKYnBfbWV0YWJpb3RhIDwtIGJyZWFrcG9pbnRzKGZvcm11bGEsIGRhdGE9dGVtcF9tZXRhYmlvdGEsaD1oKQp0ZW1wX21ldGFiaW90YSR5X2hhdCA8LSBmaXR0ZWQudmFsdWVzKGJwX21ldGFiaW90YSkKdGVtcF9tZXRhYmlvdGEkZ3JvdXBzIDwtIDA7IHRlbXBfbWV0YWJpb3RhJGdyb3Vwc1ticF9tZXRhYmlvdGEkYnJlYWtwb2ludHMrMV0gPC0gMSA7IHRlbXBfbWV0YWJpb3RhJGdyb3VwcyA8LSBjdW1zdW0odGVtcF9tZXRhYmlvdGEkZ3JvdXBzKSsxCgp0ZW1wX2JpbmcgPC0gdGVtcCAlPiUgZmlsdGVyKGRhdGFzZXQ9PSJiaW5nIikKYnBfYmluZyA8LSBicmVha3BvaW50cyhmb3JtdWxhLCBkYXRhPXRlbXBfYmluZyxoPWgpICN0aGlzIGZhaWxzIGJjIHRvbyBmZXcKbG1fYmluZyA8LWxtKGZvcm11bGEsIGRhdGE9dGVtcF9iaW5nKQp0ZW1wX2JpbmckeV9oYXQgPC0gZml0dGVkLnZhbHVlcyhsbV9iaW5nKQp0ZW1wX2JpbmckZ3JvdXBzIDwtMQoKdGVtcF9kZiA8LSBiaW5kX3Jvd3ModGVtcF9jb3ZpZHRyYWNraW5nLCB0ZW1wX3dpa2lwZWRpYSwgdGVtcF9tZXRhYmlvdGEsIHRlbXBfYmluZykgJT4lIAogICAgICAgICAgICBhcnJhbmdlKGRhdGFzZXQsZGF0ZV9hc2RhdGUpICU+JSAKICAgICAgICAgICBtdXRhdGUoZ3JvdXBzPXBhc3RlKGRhdGFzZXQsZ3JvdXBzKSkKCnRlbXBfZGYyIDwtIGJpbmRfcm93cyh0ZW1wX2NvdmlkdHJhY2tpbmcsIHRlbXBfd2lraXBlZGlhLCB0ZW1wX21ldGFiaW90YSwgdGVtcF9iaW5nKSAlPiUgCiAgICAgICAgICAgIGFycmFuZ2UoZGF0ZV9hc2RhdGUpICU+JSAKICAgICAgICAgICAgZ3JvdXBfYnkoZGF0ZV9hc2RhdGUpICU+JQogICAgICAgICAgICAgIHN1bW1hcmlzZSh5X2hhdF9tZWFuPW1lYW4oeV9oYXQsIG5hLnJtPVQpKSAlPiUKICAgICAgICAgICAgbXV0YXRlKGdyb3Vwcz05OSkKCmdncGxvdCgpICsgCiAgIGdlb21fcG9pbnQoZGF0YT10ZW1wX2RmLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT1jb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjMpICsKICAgZ2VvbV9saW5lKGRhdGE9dGVtcF9kZiwgYWVzKHg9ZGF0ZV9hc2RhdGUsIHk9eV9oYXQsIGNvbG9yPWRhdGFzZXQsIGdyb3VwPWdyb3VwcykpICsKICAgI2dlb21fbGluZShkYXRhPXRlbXBfZGYyLCBhZXMoeD1kYXRlX2FzZGF0ZSwgeT15X2hhdF9tZWFuKSwgY29sb3I9ImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICB0aGVtZV9idygpICsKICAgZ2d0aXRsZSgiRmxvcmlkYSAoUTgxMikgQ29uZmlybWVkIikKCmBgYAoKCgpgYGB7ciwgZXZhbD1GLCBlY2hvPUYsd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFfQojQXMgd2FzIHRoaXMgcGFydAojICMgUTY2OCAgUTE2ODYxICBRMTQ4ICBRMzAgUTE0OCBRMTY4NjEgUTMwCnRlbXAgPC0gdGVtcF9kZiAlPiUgZmlsdGVyKHdpa2lkYXRhX2lkPT0iUTE0OCIpICU+JSBtdXRhdGUoZGF0ZV9hc251bWVyaWM9YXMubnVtZXJpYyhkYXRlX2FzZGF0ZSkpCnRlbXAgJT4lIGdncGxvdCgpICsgZ2VvbV9wb2ludChhZXMoZGF0ZV9hc2RhdGUsY29uZmlybWVkX2xvZykpICArIGZhY2V0X3dyYXAofmRhdGFzZXQpICMrIGdlb21fcG9pbnQoYWVzKGRhdGVfYXNkYXRlLGNvbmZpcm1lZF9sb2dfeV9oYXQpLCBjb2xvcj0iYmx1ZSIpCgojbGlicmFyeShycGFydCkKI3J0IDwtIHJwYXJ0KGNvbmZpcm1lZF9sb2cgfiAxICsgZGF0ZV9hc2RhdGUgLCBkYXRhPXRlbXApCiN0ZW1wJHlfaGF0IDwtIHByZWRpY3QoIHJ0LCBuZXdkYXRhPXRlbXAgKQoKI3RlbXAkZGF0YXNldCA8LSBhcy5mYWN0b3IodGVtcCRkYXRhc2V0KQojZm1CSCA8LSBtb2IoY29uZmlybWVkX2xvZyB+IDEgKyB0ICsgSSh0XjIpICsgSSh0XjMpIHwgdCArIGRhdGFzZXQsIGNvbnRyb2wgPSBtb2JfY29udHJvbChtaW5zcGxpdCA9IDMpLCBkYXRhID0gdGVtcCwgIG1vZGVsID0gbGluZWFyTW9kZWwpICN0aGlzIGZpdHMgYSBwaWVjZXdpc2UgbGluZWFyIHRvIGVhY2ggZGF0YXNldCAjaGF2ZSB0byB1c2UgdCwgZG9lc24ndCBsaWtlIGRhdGEgb2JqZWN0cwojcGxvdChmbUJIKQojY29lZihmbUJIKQojdGVtcCR5X2hhdCA8LSBwcmVkaWN0KCBmbUJILCBuZXdkYXRhPXRlbXAgKQoKI1RoZSB0cmljayBpcyBmaXR0aW5nIG9ubHkgdG8gb25lIGRhdGFzZXQgYXQgYSB0aW1lCnRlbXBfbGlzdCA8LSBsaXN0KCkKZm9yKCBkIGluIHRlbXAkZGF0YXNldCAlPiUgdW5pcXVlKCkgKXsKICB0ZW1wdGVtcCA8LSB0ZW1wICU+JSBmaWx0ZXIoZGF0YXNldD09ZCkKICBmbUJIIDwtIG1vYihjb25maXJtZWRfbG9nIH4gMSArIGRhdGVfYXNudW1lcmljICAgIHwgZGF0ZV9hc251bWVyaWMgLCBjb250cm9sID0gbW9iX2NvbnRyb2wobWluc3BsaXQgPSAzLCBhbHBoYT0uMiksIGRhdGEgPSB0ZW1wdGVtcCwgIG1vZGVsID0gbGluZWFyTW9kZWwpICAjICsgSShkYXRlX2FzbnVtZXJpY14yKSAgICAgKyBJKHReMykgICMgKyBJKHReMikgKyBJKHReMykgKyBJKHReNCkgKyBJKHReMikgCiAgdGVtcHRlbXAkeV9oYXQgPC0gcHJlZGljdCggZm1CSCwgbmV3ZGF0YT10ZW1wdGVtcCAsIHR5cGUgPSBjKCJyZXNwb25zZSIpICkKICB0ZW1wdGVtcCRncm91cF9udW1iZXIgPC0gIHByZWRpY3QoIGZtQkgsIG5ld2RhdGE9dGVtcHRlbXAgLCB0eXBlID0gYygibm9kZSIpKQogIHRlbXB0ZW1wIDwtIHRlbXB0ZW1wICU+JSBncm91cF9ieShncm91cF9udW1iZXIpICU+JSBhcnJhbmdlKGRhdGVfYXNudW1lcmljKSAlPiUgbXV0YXRlKHNsb3BlPXRzaWJibGU6OmRpZmZlcmVuY2UoeV9oYXQpKSAlPiUgZmlsbChzbG9wZSwgLmRpcmVjdGlvbj0idXAiKSAlPiUgdW5ncm91cCgpICU+JQogICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHBlcmNlbnRfY2hhbmdlID0gcm91bmQoKGV4cChzbG9wZSktMSkqMTAwLDIpKSAKCiAgdGVtcF9saXN0W1tkXV0gPC0gdGVtcHRlbXAKfQoKY29tYmluZWQgPC0gYmluZF9yb3dzKHRlbXBfbGlzdCkgCnAwIDwtIGNvbWJpbmVkICU+JQogICAgIG11dGF0ZShncm91cD1wYXN0ZSh3aWtpZGF0YV9pZCwgZGF0YXNldCwgZ3JvdXBfbnVtYmVyKSkgJT4lCiAgICAgZ2dwbG90KCkgKyBnZW9tX3BvaW50KGFlcyhkYXRlX2FzZGF0ZSxjb25maXJtZWRfbG9nLCBjb2xvcj1kYXRhc2V0KSwgYWxwaGE9LjUpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fbGluZShhZXMoZGF0ZV9hc2RhdGUseV9oYXQsIGdyb3VwPWdyb3VwKSwgY29sb3I9ImJsdWUiLCBhbHBoYT0xKSArIGZhY2V0X3dyYXAofmRhdGFzZXQpICsgdGhlbWVfYncoKSAjaXQgc2hpdHMgdGhlIGJlZCBpbiB0aGF0IGJpZyBnYXAgaW4gd2lraXBlZGlhCgpmbUJIX3Nsb3BlIDwtIG1vYihjb25maXJtZWRfbG9nIH4gMSAgIHwgZGF0ZV9hc251bWVyaWMgLCBjb250cm9sID0gbW9iX2NvbnRyb2wobWluc3BsaXQgPSAzLCBhbHBoYT0uMSksIGRhdGEgPSBjb21iaW5lZCwgIG1vZGVsID0gbGluZWFyTW9kZWwpICAjaXQgZG9lc24ndCB3YW50IHRvIGRvIApydDEgPC0gcnBhcnQoZm9ybXVsYSA9IHBlcmNlbnRfY2hhbmdlIH4gZGF0ZV9hc251bWVyaWMsIGRhdGE9Y29tYmluZWQpCmNvbWJpbmVkJHBlcmNlbnRfY2hhbmdlX3lfaGF0IDwtICBwcmVkaWN0KHJ0MSwgbmV3ZGF0YT1jb21iaW5lZCkKI2NvbWJpbmVkJHNsb3BlX3lfaGF0IDwtIHByZWRpY3QoIGZtQkhfc2xvcGUsIG5ld2RhdGE9Y29tYmluZWQgICwgdHlwZSA9IGMoInJlc3BvbnNlIikgKQojY29tYmluZWQkZ3JvdXBfbnVtYmVyIDwtIHByZWRpY3QoIGZtQkhfc2xvcGUsIG5ld2RhdGE9Y29tYmluZWQgICwgdHlwZSA9IGMoIm5vZGUiKSApCgpwMSA8LSBjb21iaW5lZCAlPiUKICAgICBtdXRhdGUoZ3JvdXA9cGFzdGUod2lraWRhdGFfaWQsIGRhdGFzZXQsIGdyb3VwX251bWJlcikpICU+JQogICAgIGdncGxvdCgpICsgZ2VvbV9wb2ludChhZXMoZGF0ZV9hc2RhdGUsY29uZmlybWVkX2xvZywgY29sb3I9ZGF0YXNldCksIGFscGhhPS41KSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2xpbmUoYWVzKGRhdGVfYXNkYXRlLHlfaGF0LCBncm91cD1ncm91cCwgY29sb3I9ZGF0YXNldCksIGFscGhhPS4xKSArIHRoZW1lX2J3KCkgKyBmYWNldF93cmFwKH5kYXRhc2V0KSMgICNpdCBzaGl0cyB0aGUgYmVkIGluIHRoYXQgYmlnIGdhcCBpbiB3aWtpcGVkaWEKCgpwMiA8LSBjb21iaW5lZCAlPiUgZ2dwbG90KCkgKyBnZW9tX3BvaW50KGFlcyhkYXRlX2FzZGF0ZSxwZXJjZW50X2NoYW5nZV95X2hhdCwgY29sb3I9ZGF0YXNldCksIGFscGhhPS41KSArIAogICAgICAgICAgICAgZ2VvbV9saW5lKGFlcyhkYXRlX2FzZGF0ZSxwZXJjZW50X2NoYW5nZV95X2hhdCksIGNvbG9yPSJibGFjayIsIGFscGhhPTEpICsgdGhlbWVfYncoKSArIGZhY2V0X3dyYXAofmRhdGFzZXQpICMrIGZhY2V0X3dyYXAofmRhdGFzZXQpICNpdCBzaGl0cyB0aGUgYmVkIGluIHRoYXQgYmlnIGdhcCBpbiB3aWtpcGVkaWEKCnAxIC8gcDIKCgpgYGAKCgo=